[PGO] Reduce IO in profile dumping with merging
Differential Revision: http://reviews.llvm.org/D34709 llvm-svn: 306561
This commit is contained in:
parent
4e96f19052
commit
f50cc3ed8a
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue