Skip to content

Commit 5a486e0

Browse files
committed
[profile] Avoid allocating a page on the stack, NFC
When writing out a profile, avoid allocating a page on the stack for the purpose of writing out zeroes, as some embedded environments do not have enough stack space to accomodate this. Instead, use a small, fixed-size zero buffer that can be written repeatedly. For a synthetic file with >100,000 functions, I did not measure a significant difference in profile write times. We are removing a page-length zero-fill `memset()` in favor of several smaller buffered `fwrite()` calls: in practice, I am not sure there is much of a difference. The performance impact is only expected to affect the continuous sync mode (%c) -- zero padding is less than 8 bytes in all other cases. rdar://57810014 Differential Revision: https://reviews.llvm.org/D71323
1 parent d25437e commit 5a486e0

File tree

4 files changed

+33
-14
lines changed

4 files changed

+33
-14
lines changed

compiler-rt/lib/profile/InstrProfilingFile.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,23 @@ static uint32_t fileWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
122122
uint32_t NumIOVecs) {
123123
uint32_t I;
124124
FILE *File = (FILE *)This->WriterCtx;
125+
char Zeroes[sizeof(uint64_t)] = {0};
125126
for (I = 0; I < NumIOVecs; I++) {
126127
if (IOVecs[I].Data) {
127128
if (fwrite(IOVecs[I].Data, IOVecs[I].ElmSize, IOVecs[I].NumElm, File) !=
128129
IOVecs[I].NumElm)
129130
return 1;
131+
} else if (IOVecs[I].UseZeroPadding) {
132+
size_t BytesToWrite = IOVecs[I].ElmSize * IOVecs[I].NumElm;
133+
while (BytesToWrite > 0) {
134+
size_t PartialWriteLen =
135+
(sizeof(uint64_t) > BytesToWrite) ? BytesToWrite : sizeof(uint64_t);
136+
if (fwrite(Zeroes, sizeof(uint8_t), PartialWriteLen, File) !=
137+
PartialWriteLen) {
138+
return 1;
139+
}
140+
BytesToWrite -= PartialWriteLen;
141+
}
130142
} else {
131143
if (fseek(File, IOVecs[I].ElmSize * IOVecs[I].NumElm, SEEK_CUR) == -1)
132144
return 1;

compiler-rt/lib/profile/InstrProfilingInternal.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,18 @@ int __llvm_profile_write_buffer_internal(
4141
/*!
4242
* The data structure describing the data to be written by the
4343
* low level writer callback function.
44+
*
45+
* If \ref ProfDataIOVec.Data is null, and \ref ProfDataIOVec.UseZeroPadding is
46+
* 0, the write is skipped (the writer simply advances ElmSize*NumElm bytes).
47+
*
48+
* If \ref ProfDataIOVec.Data is null, and \ref ProfDataIOVec.UseZeroPadding is
49+
* nonzero, ElmSize*NumElm zero bytes are written.
4450
*/
4551
typedef struct ProfDataIOVec {
4652
const void *Data;
4753
size_t ElmSize;
4854
size_t NumElm;
55+
int UseZeroPadding;
4956
} ProfDataIOVec;
5057

5158
struct ProfDataWriter;

compiler-rt/lib/profile/InstrProfilingPlatformFuchsia.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ static uint32_t lprofVMOWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
128128
__llvm_profile_offset, Length);
129129
if (Status != ZX_OK)
130130
return -1;
131+
} else if (IOVecs[I].UseZeroPadding) {
132+
/* Resizing the VMO should zero fill. */
131133
}
132134
__llvm_profile_offset += Length;
133135
}

compiler-rt/lib/profile/InstrProfilingWriter.c

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ COMPILER_RT_VISIBILITY uint32_t lprofBufferWriter(ProfDataWriter *This,
4141
size_t Length = IOVecs[I].ElmSize * IOVecs[I].NumElm;
4242
if (IOVecs[I].Data)
4343
memcpy(*Buffer, IOVecs[I].Data, Length);
44+
else if (IOVecs[I].UseZeroPadding) {
45+
/* Allocating the buffer should zero fill. */
46+
}
4447
*Buffer += Length;
4548
}
4649
return 0;
@@ -85,7 +88,7 @@ lprofBufferIOWrite(ProfBufferIO *BufferIO, const uint8_t *Data, uint32_t Size) {
8588
return -1;
8689
}
8790
/* Special case, bypass the buffer completely. */
88-
ProfDataIOVec IO[] = {{Data, sizeof(uint8_t), Size}};
91+
ProfDataIOVec IO[] = {{Data, sizeof(uint8_t), Size, 0}};
8992
if (Size > BufferIO->BufferSz) {
9093
if (BufferIO->FileWriter->Write(BufferIO->FileWriter, IO, 1))
9194
return -1;
@@ -104,7 +107,7 @@ lprofBufferIOWrite(ProfBufferIO *BufferIO, const uint8_t *Data, uint32_t Size) {
104107
COMPILER_RT_VISIBILITY int lprofBufferIOFlush(ProfBufferIO *BufferIO) {
105108
if (BufferIO->CurOffset) {
106109
ProfDataIOVec IO[] = {
107-
{BufferIO->BufferStart, sizeof(uint8_t), BufferIO->CurOffset}};
110+
{BufferIO->BufferStart, sizeof(uint8_t), BufferIO->CurOffset, 0}};
108111
if (BufferIO->FileWriter->Write(BufferIO->FileWriter, IO, 1))
109112
return -1;
110113
BufferIO->CurOffset = 0;
@@ -259,11 +262,6 @@ lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin,
259262
const uint64_t CountersSize = CountersEnd - CountersBegin;
260263
const uint64_t NamesSize = NamesEnd - NamesBegin;
261264

262-
/* Enough zeroes for padding. */
263-
unsigned PageSize = getpagesize();
264-
char *Zeroes = (char *)COMPILER_RT_ALLOCA(PageSize);
265-
memset(Zeroes, 0, PageSize);
266-
267265
/* Create the header. */
268266
__llvm_profile_header Header;
269267

@@ -284,13 +282,13 @@ lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin,
284282

285283
/* Write the data. */
286284
ProfDataIOVec IOVec[] = {
287-
{&Header, sizeof(__llvm_profile_header), 1},
288-
{DataBegin, sizeof(__llvm_profile_data), DataSize},
289-
{Zeroes, sizeof(uint8_t), PaddingBytesBeforeCounters},
290-
{CountersBegin, sizeof(uint64_t), CountersSize},
291-
{Zeroes, sizeof(uint8_t), PaddingBytesAfterCounters},
292-
{SkipNameDataWrite ? NULL : NamesBegin, sizeof(uint8_t), NamesSize},
293-
{Zeroes, sizeof(uint8_t), PaddingBytesAfterNames}};
285+
{&Header, sizeof(__llvm_profile_header), 1, 0},
286+
{DataBegin, sizeof(__llvm_profile_data), DataSize, 0},
287+
{NULL, sizeof(uint8_t), PaddingBytesBeforeCounters, 1},
288+
{CountersBegin, sizeof(uint64_t), CountersSize, 0},
289+
{NULL, sizeof(uint8_t), PaddingBytesAfterCounters, 1},
290+
{SkipNameDataWrite ? NULL : NamesBegin, sizeof(uint8_t), NamesSize, 0},
291+
{NULL, sizeof(uint8_t), PaddingBytesAfterNames, 1}};
294292
if (Writer->Write(Writer, IOVec, sizeof(IOVec) / sizeof(*IOVec)))
295293
return -1;
296294

0 commit comments

Comments
 (0)