Skip to content

Commit 38dfa22

Browse files
committed
Draft changes to trim the histogram raw profile format.
1 parent 7563531 commit 38dfa22

File tree

5 files changed

+78
-9
lines changed

5 files changed

+78
-9
lines changed

compiler-rt/include/profile/MemProfData.inc

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@
3333
(uint64_t)'o' << 24 | (uint64_t)'f' << 16 | (uint64_t)'r' << 8 | (uint64_t)129)
3434

3535
// The version number of the raw binary format.
36-
#define MEMPROF_RAW_VERSION 4ULL
36+
#define MEMPROF_RAW_VERSION 5ULL
3737

3838
// Currently supported versions.
3939
#define MEMPROF_RAW_SUPPORTED_VERSIONS \
40-
{ 3ULL, 4ULL }
40+
{ 3ULL, 4ULL, 5ULL }
4141

4242
#define MEMPROF_V3_MIB_SIZE 132ULL;
4343

@@ -219,7 +219,11 @@ void Merge(const MemInfoBlock &newMIB) {
219219
ShorterHistogramSize = newMIB.AccessHistogramSize;
220220
}
221221
for (size_t i = 0; i < ShorterHistogramSize; ++i) {
222-
((uint64_t *)AccessHistogram)[i] += ((uint64_t *)ShorterHistogram)[i];
222+
// Cast to uint8_t* and cap the sum at 255 to prevent overflow
223+
uint8_t *CurrentHistPtr = (uint8_t *)AccessHistogram;
224+
uint8_t *ShorterHistPtr = (uint8_t *)ShorterHistogram;
225+
uint32_t sum = CurrentHistPtr[i] + ShorterHistPtr[i];
226+
CurrentHistPtr[i] = (sum > 255) ? 255 : (uint8_t)sum;
223227
}
224228
}
225229

compiler-rt/lib/memprof/memprof_allocator.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ void Print(const MemInfoBlock &M, const u64 id, bool print_terse) {
7777
? MAX_HISTOGRAM_PRINT_SIZE
7878
: M.AccessHistogramSize;
7979
for (size_t i = 0; i < PrintSize; ++i) {
80-
Printf("%llu ", ((uint64_t *)M.AccessHistogram)[i]);
80+
Printf("%u ", ((uint8_t *)M.AccessHistogram)[i]);
8181
}
8282
Printf("\n");
8383
}
@@ -327,12 +327,13 @@ struct Allocator {
327327
uint32_t HistogramSize =
328328
RoundUpTo(user_size, HISTOGRAM_GRANULARITY) / HISTOGRAM_GRANULARITY;
329329
uintptr_t Histogram =
330-
(uintptr_t)InternalAlloc(HistogramSize * sizeof(uint64_t));
331-
memset((void *)Histogram, 0, HistogramSize * sizeof(uint64_t));
330+
(uintptr_t)InternalAlloc(HistogramSize * sizeof(uint8_t));
331+
memset((void *)Histogram, 0, HistogramSize * sizeof(uint8_t));
332332
for (size_t i = 0; i < HistogramSize; ++i) {
333333
u8 Counter =
334334
*((u8 *)HISTOGRAM_MEM_TO_SHADOW(p + HISTOGRAM_GRANULARITY * i));
335-
((uint64_t *)Histogram)[i] = (uint64_t)Counter;
335+
// Cap the counter at HISTOGRAM_MAX_COUNTER (255) to prevent overflow
336+
((uint8_t *)Histogram)[i] = (Counter > HISTOGRAM_MAX_COUNTER) ? HISTOGRAM_MAX_COUNTER : Counter;
336337
}
337338
MemInfoBlock newMIB(user_size, c, m->timestamp_ms, curtime, m->cpu_id,
338339
GetCpuId(), Histogram, HistogramSize);

compiler-rt/lib/memprof/memprof_rawprofile.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ void SerializeMIBInfoToBuffer(MIBMapTy &MIBMap, const Vector<u64> &StackIds,
171171
// deserialization.
172172
Ptr = WriteBytes((*h)->mib, Ptr);
173173
for (u64 j = 0; j < (*h)->mib.AccessHistogramSize; ++j) {
174-
u64 HistogramEntry = ((u64 *)((*h)->mib.AccessHistogram))[j];
174+
// Read as uint8_t and write as uint8_t
175+
uint8_t HistogramEntry = ((uint8_t *)((*h)->mib.AccessHistogram))[j];
175176
Ptr = WriteBytes(HistogramEntry, Ptr);
176177
}
177178
if ((*h)->mib.AccessHistogramSize > 0) {
@@ -249,7 +250,7 @@ u64 SerializeToRawProfile(MIBMapTy &MIBMap, ArrayRef<LoadedModule> Modules,
249250
},
250251
reinterpret_cast<void *>(&TotalAccessHistogramEntries));
251252
const u64 NumHistogramBytes =
252-
RoundUpTo(TotalAccessHistogramEntries * sizeof(uint64_t), 8);
253+
RoundUpTo(TotalAccessHistogramEntries * sizeof(uint8_t), 8);
253254

254255
const u64 NumStackBytes = RoundUpTo(StackSizeBytes(StackIds), 8);
255256

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Test for memprof histogram bounds checking (255 limit)
2+
// RUN: %clangxx_memprof -O0 %s -o %t && %env_memprof_opts=print_text=1:histogram=1 %run %t 2>&1 | FileCheck %s
3+
4+
#include <stdio.h>
5+
#include <stdlib.h>
6+
#include <string.h>
7+
8+
int main() {
9+
// Allocate memory
10+
char *buffer = (char *)malloc(256);
11+
if (!buffer) return 1;
12+
13+
// Access a single byte many times to test counter overflow protection
14+
// This should create a counter that would exceed 255 if not capped
15+
for (int i = 0; i < 300; ++i) {
16+
buffer[0] = 'X';
17+
}
18+
19+
// Access another byte fewer times
20+
for (int i = 0; i < 100; ++i) {
21+
buffer[8] = 'Y';
22+
}
23+
24+
// Free to trigger histogram creation
25+
free(buffer);
26+
27+
printf("Bounds test completed\n");
28+
return 0;
29+
}
30+
31+
// CHECK: AccessCountHistogram
32+
// CHECK: Bounds test completed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Test for memprof histogram uint8_t optimization
2+
// RUN: %clangxx_memprof -O0 %s -o %t && %env_memprof_opts=print_text=1:histogram=1 %run %t 2>&1 | FileCheck %s
3+
4+
#include <stdio.h>
5+
#include <stdlib.h>
6+
#include <string.h>
7+
8+
int main() {
9+
// Allocate memory that will create a histogram
10+
char *buffer = (char *)malloc(1024);
11+
if (!buffer) return 1;
12+
13+
// Access pattern: write to specific bytes to create histogram entries
14+
for (int i = 0; i < 10; ++i) {
15+
buffer[i * 8] = 'A'; // Access every 8th byte to create histogram patterns
16+
}
17+
18+
// Access some bytes multiple times to test counter behavior
19+
for (int j = 0; j < 200; ++j) {
20+
buffer[0] = 'B'; // This should create a counter value that stays within uint8_t range
21+
}
22+
23+
// Free the memory to trigger MIB creation with histogram
24+
free(buffer);
25+
26+
printf("Test completed successfully\n");
27+
return 0;
28+
}
29+
30+
// CHECK: AccessCountHistogram
31+
// CHECK: Test completed successfully

0 commit comments

Comments
 (0)