[PGO] Reduce IO in profile dumping with merging

Differential Revision: http://reviews.llvm.org/D34709

llvm-svn: 306561
This commit is contained in:
Xinliang David Li 2017-06-28 16:46:06 +00:00
parent 4e96f19052
commit f50cc3ed8a
4 changed files with 39 additions and 25 deletions

View File

@ -54,7 +54,7 @@ void initBufferWriter(ProfDataWriter *BufferWriter, char *Buffer) {
COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer(char *Buffer) { COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer(char *Buffer) {
ProfDataWriter BufferWriter; ProfDataWriter BufferWriter;
initBufferWriter(&BufferWriter, Buffer); initBufferWriter(&BufferWriter, Buffer);
return lprofWriteData(&BufferWriter, 0); return lprofWriteData(&BufferWriter, 0, 0);
} }
COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer_internal( COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer_internal(
@ -64,5 +64,5 @@ COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer_internal(
ProfDataWriter BufferWriter; ProfDataWriter BufferWriter;
initBufferWriter(&BufferWriter, Buffer); initBufferWriter(&BufferWriter, Buffer);
return lprofWriteDataImpl(&BufferWriter, DataBegin, DataEnd, CountersBegin, return lprofWriteDataImpl(&BufferWriter, DataBegin, DataEnd, CountersBegin,
CountersEnd, 0, NamesBegin, NamesEnd); CountersEnd, 0, NamesBegin, NamesEnd, 0);
} }

View File

@ -93,13 +93,17 @@ static unsigned doMerging() { return lprofCurFilename.MergePoolSize; }
/* Return 1 if there is an error, otherwise return 0. */ /* Return 1 if there is an error, otherwise return 0. */
static uint32_t fileWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs, static uint32_t fileWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
uint32_t NumIOVecs) { uint32_t NumIOVecs) {
uint32_t I; uint32_t I;
FILE *File = (FILE *)This->WriterCtx; FILE *File = (FILE *)This->WriterCtx;
for (I = 0; I < NumIOVecs; I++) { for (I = 0; I < NumIOVecs; I++) {
if (fwrite(IOVecs[I].Data, IOVecs[I].ElmSize, IOVecs[I].NumElm, File) != if (IOVecs[I].Data) {
IOVecs[I].NumElm) if (fwrite(IOVecs[I].Data, IOVecs[I].ElmSize, IOVecs[I].NumElm, File) !=
return 1; IOVecs[I].NumElm)
return 1;
} else {
if (fseek(File, IOVecs[I].ElmSize * IOVecs[I].NumElm, SEEK_CUR) == -1)
return 1;
}
} }
return 0; return 0;
} }
@ -133,9 +137,10 @@ static void setupIOBuffer() {
/* Read profile data in \c ProfileFile and merge with in-memory /* Read profile data in \c ProfileFile and merge with in-memory
profile counters. Returns -1 if there is fatal error, otheriwse profile counters. Returns -1 if there is fatal error, otheriwse
0 is returned. 0 is returned. Returning 0 does not mean merge is actually
performed. If merge is actually done, *MergeDone is set to 1.
*/ */
static int doProfileMerging(FILE *ProfileFile) { static int doProfileMerging(FILE *ProfileFile, int *MergeDone) {
uint64_t ProfileFileSize; uint64_t ProfileFileSize;
char *ProfileBuffer; char *ProfileBuffer;
@ -180,6 +185,8 @@ static int doProfileMerging(FILE *ProfileFile) {
__llvm_profile_merge_from_buffer(ProfileBuffer, ProfileFileSize); __llvm_profile_merge_from_buffer(ProfileBuffer, ProfileFileSize);
(void)munmap(ProfileBuffer, ProfileFileSize); (void)munmap(ProfileBuffer, ProfileFileSize);
*MergeDone = 1;
return 0; return 0;
} }
@ -201,7 +208,7 @@ static void createProfileDir(const char *Filename) {
* dumper. With profile merging enabled, each executable as well as any of * dumper. With profile merging enabled, each executable as well as any of
* its instrumented shared libraries dump profile data into their own data file. * its instrumented shared libraries dump profile data into their own data file.
*/ */
static FILE *openFileForMerging(const char *ProfileFileName) { static FILE *openFileForMerging(const char *ProfileFileName, int *MergeDone) {
FILE *ProfileFile; FILE *ProfileFile;
int rc; int rc;
@ -210,8 +217,8 @@ static FILE *openFileForMerging(const char *ProfileFileName) {
if (!ProfileFile) if (!ProfileFile)
return NULL; return NULL;
rc = doProfileMerging(ProfileFile); rc = doProfileMerging(ProfileFile, MergeDone);
if (rc || COMPILER_RT_FTRUNCATE(ProfileFile, 0L) || if (rc || (!*MergeDone && COMPILER_RT_FTRUNCATE(ProfileFile, 0L)) ||
fseek(ProfileFile, 0L, SEEK_SET) == -1) { fseek(ProfileFile, 0L, SEEK_SET) == -1) {
PROF_ERR("Profile Merging of file %s failed: %s\n", ProfileFileName, PROF_ERR("Profile Merging of file %s failed: %s\n", ProfileFileName,
strerror(errno)); strerror(errno));
@ -226,10 +233,11 @@ static int writeFile(const char *OutputName) {
int RetVal; int RetVal;
FILE *OutputFile; FILE *OutputFile;
int MergeDone = 0;
if (!doMerging()) if (!doMerging())
OutputFile = fopen(OutputName, "ab"); OutputFile = fopen(OutputName, "ab");
else else
OutputFile = openFileForMerging(OutputName); OutputFile = openFileForMerging(OutputName, &MergeDone);
if (!OutputFile) if (!OutputFile)
return -1; return -1;
@ -238,7 +246,7 @@ static int writeFile(const char *OutputName) {
setupIOBuffer(); setupIOBuffer();
ProfDataWriter fileWriter; ProfDataWriter fileWriter;
initFileWriter(&fileWriter, OutputFile); initFileWriter(&fileWriter, OutputFile);
RetVal = lprofWriteData(&fileWriter, lprofGetVPDataReader()); RetVal = lprofWriteData(&fileWriter, lprofGetVPDataReader(), MergeDone);
fclose(OutputFile); fclose(OutputFile);
return RetVal; return RetVal;

View File

@ -102,7 +102,6 @@ int lprofBufferIOFlush(ProfBufferIO *BufferIO);
* and profile data writer. */ * and profile data writer. */
uint32_t lprofBufferWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs, uint32_t lprofBufferWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
uint32_t NumIOVecs); uint32_t NumIOVecs);
void initBufferWriter(ProfDataWriter *BufferWriter, char *Buffer); void initBufferWriter(ProfDataWriter *BufferWriter, char *Buffer);
struct ValueProfData; struct ValueProfData;
@ -139,14 +138,17 @@ typedef struct VPDataReaderType {
uint32_t N); uint32_t N);
} VPDataReaderType; } VPDataReaderType;
int lprofWriteData(ProfDataWriter *Writer, VPDataReaderType *VPDataReader); /* Write profile data to destinitation. If SkipNameDataWrite is set to 1,
the name data is already in destintation, we just skip over it. */
int lprofWriteData(ProfDataWriter *Writer, VPDataReaderType *VPDataReader,
int SkipNameDataWrite);
int lprofWriteDataImpl(ProfDataWriter *Writer, int lprofWriteDataImpl(ProfDataWriter *Writer,
const __llvm_profile_data *DataBegin, const __llvm_profile_data *DataBegin,
const __llvm_profile_data *DataEnd, const __llvm_profile_data *DataEnd,
const uint64_t *CountersBegin, const uint64_t *CountersBegin,
const uint64_t *CountersEnd, const uint64_t *CountersEnd,
VPDataReaderType *VPDataReader, const char *NamesBegin, VPDataReaderType *VPDataReader, const char *NamesBegin,
const char *NamesEnd); const char *NamesEnd, int SkipNameDataWrite);
/* Merge value profile data pointed to by SrcValueProfData into /* Merge value profile data pointed to by SrcValueProfData into
* in-memory profile counters pointed by to DstData. */ * in-memory profile counters pointed by to DstData. */

View File

@ -38,7 +38,8 @@ COMPILER_RT_VISIBILITY uint32_t lprofBufferWriter(ProfDataWriter *This,
char **Buffer = (char **)&This->WriterCtx; char **Buffer = (char **)&This->WriterCtx;
for (I = 0; I < NumIOVecs; I++) { for (I = 0; I < NumIOVecs; I++) {
size_t Length = IOVecs[I].ElmSize * IOVecs[I].NumElm; size_t Length = IOVecs[I].ElmSize * IOVecs[I].NumElm;
memcpy(*Buffer, IOVecs[I].Data, Length); if (IOVecs[I].Data)
memcpy(*Buffer, IOVecs[I].Data, Length);
*Buffer += Length; *Buffer += Length;
} }
return 0; return 0;
@ -231,7 +232,8 @@ static int writeValueProfData(ProfDataWriter *Writer,
} }
COMPILER_RT_VISIBILITY int lprofWriteData(ProfDataWriter *Writer, COMPILER_RT_VISIBILITY int lprofWriteData(ProfDataWriter *Writer,
VPDataReaderType *VPDataReader) { VPDataReaderType *VPDataReader,
int SkipNameDataWrite) {
/* Match logic in __llvm_profile_write_buffer(). */ /* Match logic in __llvm_profile_write_buffer(). */
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data(); const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
const __llvm_profile_data *DataEnd = __llvm_profile_end_data(); const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
@ -240,7 +242,8 @@ COMPILER_RT_VISIBILITY int lprofWriteData(ProfDataWriter *Writer,
const char *NamesBegin = __llvm_profile_begin_names(); const char *NamesBegin = __llvm_profile_begin_names();
const char *NamesEnd = __llvm_profile_end_names(); const char *NamesEnd = __llvm_profile_end_names();
return lprofWriteDataImpl(Writer, DataBegin, DataEnd, CountersBegin, return lprofWriteDataImpl(Writer, DataBegin, DataEnd, CountersBegin,
CountersEnd, VPDataReader, NamesBegin, NamesEnd); CountersEnd, VPDataReader, NamesBegin, NamesEnd,
SkipNameDataWrite);
} }
COMPILER_RT_VISIBILITY int COMPILER_RT_VISIBILITY int
@ -248,7 +251,7 @@ lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin,
const __llvm_profile_data *DataEnd, const __llvm_profile_data *DataEnd,
const uint64_t *CountersBegin, const uint64_t *CountersEnd, const uint64_t *CountersBegin, const uint64_t *CountersEnd,
VPDataReaderType *VPDataReader, const char *NamesBegin, VPDataReaderType *VPDataReader, const char *NamesBegin,
const char *NamesEnd) { const char *NamesEnd, int SkipNameDataWrite) {
/* Calculate size of sections. */ /* Calculate size of sections. */
const uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd); const uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
@ -270,11 +273,12 @@ lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin,
#include "InstrProfData.inc" #include "InstrProfData.inc"
/* Write the data. */ /* Write the data. */
ProfDataIOVec IOVec[] = {{&Header, sizeof(__llvm_profile_header), 1}, ProfDataIOVec IOVec[] = {
{DataBegin, sizeof(__llvm_profile_data), DataSize}, {&Header, sizeof(__llvm_profile_header), 1},
{CountersBegin, sizeof(uint64_t), CountersSize}, {DataBegin, sizeof(__llvm_profile_data), DataSize},
{NamesBegin, sizeof(uint8_t), NamesSize}, {CountersBegin, sizeof(uint64_t), CountersSize},
{Zeroes, sizeof(uint8_t), Padding}}; {SkipNameDataWrite ? NULL : NamesBegin, sizeof(uint8_t), NamesSize},
{Zeroes, sizeof(uint8_t), Padding}};
if (Writer->Write(Writer, IOVec, sizeof(IOVec) / sizeof(*IOVec))) if (Writer->Write(Writer, IOVec, sizeof(IOVec) / sizeof(*IOVec)))
return -1; return -1;