diff options
author | Vedant Kumar <vsk@apple.com> | 2019-12-10 18:17:28 -0800 |
---|---|---|
committer | Vedant Kumar <vsk@apple.com> | 2019-12-11 10:04:00 -0800 |
commit | 5a486e0f156ce62b445ccf7b3ea15dd45394ea1c (patch) | |
tree | 249d2a5a0e495f1da7579c23bbd75d0267f86204 | |
parent | d25437e957549bdab46f1a052bad4f330d31a9e1 (diff) | |
download | bcm5719-llvm-5a486e0f156ce62b445ccf7b3ea15dd45394ea1c.tar.gz bcm5719-llvm-5a486e0f156ce62b445ccf7b3ea15dd45394ea1c.zip |
[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
-rw-r--r-- | compiler-rt/lib/profile/InstrProfilingFile.c | 12 | ||||
-rw-r--r-- | compiler-rt/lib/profile/InstrProfilingInternal.h | 7 | ||||
-rw-r--r-- | compiler-rt/lib/profile/InstrProfilingPlatformFuchsia.c | 2 | ||||
-rw-r--r-- | compiler-rt/lib/profile/InstrProfilingWriter.c | 26 |
4 files changed, 33 insertions, 14 deletions
diff --git a/compiler-rt/lib/profile/InstrProfilingFile.c b/compiler-rt/lib/profile/InstrProfilingFile.c index d775f6b2040..3abf7a79619 100644 --- a/compiler-rt/lib/profile/InstrProfilingFile.c +++ b/compiler-rt/lib/profile/InstrProfilingFile.c @@ -122,11 +122,23 @@ static uint32_t fileWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs, uint32_t NumIOVecs) { uint32_t I; FILE *File = (FILE *)This->WriterCtx; + char Zeroes[sizeof(uint64_t)] = {0}; for (I = 0; I < NumIOVecs; I++) { if (IOVecs[I].Data) { if (fwrite(IOVecs[I].Data, IOVecs[I].ElmSize, IOVecs[I].NumElm, File) != IOVecs[I].NumElm) return 1; + } else if (IOVecs[I].UseZeroPadding) { + size_t BytesToWrite = IOVecs[I].ElmSize * IOVecs[I].NumElm; + while (BytesToWrite > 0) { + size_t PartialWriteLen = + (sizeof(uint64_t) > BytesToWrite) ? BytesToWrite : sizeof(uint64_t); + if (fwrite(Zeroes, sizeof(uint8_t), PartialWriteLen, File) != + PartialWriteLen) { + return 1; + } + BytesToWrite -= PartialWriteLen; + } } else { if (fseek(File, IOVecs[I].ElmSize * IOVecs[I].NumElm, SEEK_CUR) == -1) return 1; diff --git a/compiler-rt/lib/profile/InstrProfilingInternal.h b/compiler-rt/lib/profile/InstrProfilingInternal.h index 66f8a067701..0cea4876f0a 100644 --- a/compiler-rt/lib/profile/InstrProfilingInternal.h +++ b/compiler-rt/lib/profile/InstrProfilingInternal.h @@ -41,11 +41,18 @@ int __llvm_profile_write_buffer_internal( /*! * The data structure describing the data to be written by the * low level writer callback function. + * + * If \ref ProfDataIOVec.Data is null, and \ref ProfDataIOVec.UseZeroPadding is + * 0, the write is skipped (the writer simply advances ElmSize*NumElm bytes). + * + * If \ref ProfDataIOVec.Data is null, and \ref ProfDataIOVec.UseZeroPadding is + * nonzero, ElmSize*NumElm zero bytes are written. */ typedef struct ProfDataIOVec { const void *Data; size_t ElmSize; size_t NumElm; + int UseZeroPadding; } ProfDataIOVec; struct ProfDataWriter; diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformFuchsia.c b/compiler-rt/lib/profile/InstrProfilingPlatformFuchsia.c index 2388871a2d5..23b7efbe672 100644 --- a/compiler-rt/lib/profile/InstrProfilingPlatformFuchsia.c +++ b/compiler-rt/lib/profile/InstrProfilingPlatformFuchsia.c @@ -128,6 +128,8 @@ static uint32_t lprofVMOWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs, __llvm_profile_offset, Length); if (Status != ZX_OK) return -1; + } else if (IOVecs[I].UseZeroPadding) { + /* Resizing the VMO should zero fill. */ } __llvm_profile_offset += Length; } diff --git a/compiler-rt/lib/profile/InstrProfilingWriter.c b/compiler-rt/lib/profile/InstrProfilingWriter.c index ac8113e2f05..c34e110a695 100644 --- a/compiler-rt/lib/profile/InstrProfilingWriter.c +++ b/compiler-rt/lib/profile/InstrProfilingWriter.c @@ -41,6 +41,9 @@ COMPILER_RT_VISIBILITY uint32_t lprofBufferWriter(ProfDataWriter *This, size_t Length = IOVecs[I].ElmSize * IOVecs[I].NumElm; if (IOVecs[I].Data) memcpy(*Buffer, IOVecs[I].Data, Length); + else if (IOVecs[I].UseZeroPadding) { + /* Allocating the buffer should zero fill. */ + } *Buffer += Length; } return 0; @@ -85,7 +88,7 @@ lprofBufferIOWrite(ProfBufferIO *BufferIO, const uint8_t *Data, uint32_t Size) { return -1; } /* Special case, bypass the buffer completely. */ - ProfDataIOVec IO[] = {{Data, sizeof(uint8_t), Size}}; + ProfDataIOVec IO[] = {{Data, sizeof(uint8_t), Size, 0}}; if (Size > BufferIO->BufferSz) { if (BufferIO->FileWriter->Write(BufferIO->FileWriter, IO, 1)) return -1; @@ -104,7 +107,7 @@ lprofBufferIOWrite(ProfBufferIO *BufferIO, const uint8_t *Data, uint32_t Size) { COMPILER_RT_VISIBILITY int lprofBufferIOFlush(ProfBufferIO *BufferIO) { if (BufferIO->CurOffset) { ProfDataIOVec IO[] = { - {BufferIO->BufferStart, sizeof(uint8_t), BufferIO->CurOffset}}; + {BufferIO->BufferStart, sizeof(uint8_t), BufferIO->CurOffset, 0}}; if (BufferIO->FileWriter->Write(BufferIO->FileWriter, IO, 1)) return -1; BufferIO->CurOffset = 0; @@ -259,11 +262,6 @@ lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin, const uint64_t CountersSize = CountersEnd - CountersBegin; const uint64_t NamesSize = NamesEnd - NamesBegin; - /* Enough zeroes for padding. */ - unsigned PageSize = getpagesize(); - char *Zeroes = (char *)COMPILER_RT_ALLOCA(PageSize); - memset(Zeroes, 0, PageSize); - /* Create the header. */ __llvm_profile_header Header; @@ -284,13 +282,13 @@ lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin, /* Write the data. */ ProfDataIOVec IOVec[] = { - {&Header, sizeof(__llvm_profile_header), 1}, - {DataBegin, sizeof(__llvm_profile_data), DataSize}, - {Zeroes, sizeof(uint8_t), PaddingBytesBeforeCounters}, - {CountersBegin, sizeof(uint64_t), CountersSize}, - {Zeroes, sizeof(uint8_t), PaddingBytesAfterCounters}, - {SkipNameDataWrite ? NULL : NamesBegin, sizeof(uint8_t), NamesSize}, - {Zeroes, sizeof(uint8_t), PaddingBytesAfterNames}}; + {&Header, sizeof(__llvm_profile_header), 1, 0}, + {DataBegin, sizeof(__llvm_profile_data), DataSize, 0}, + {NULL, sizeof(uint8_t), PaddingBytesBeforeCounters, 1}, + {CountersBegin, sizeof(uint64_t), CountersSize, 0}, + {NULL, sizeof(uint8_t), PaddingBytesAfterCounters, 1}, + {SkipNameDataWrite ? NULL : NamesBegin, sizeof(uint8_t), NamesSize, 0}, + {NULL, sizeof(uint8_t), PaddingBytesAfterNames, 1}}; if (Writer->Write(Writer, IOVec, sizeof(IOVec) / sizeof(*IOVec))) return -1; |