[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) {
|
||||
ProfDataWriter BufferWriter;
|
||||
initBufferWriter(&BufferWriter, Buffer);
|
||||
return lprofWriteData(&BufferWriter, 0);
|
||||
return lprofWriteData(&BufferWriter, 0, 0);
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer_internal(
|
||||
|
@ -64,5 +64,5 @@ COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer_internal(
|
|||
ProfDataWriter BufferWriter;
|
||||
initBufferWriter(&BufferWriter, Buffer);
|
||||
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. */
|
||||
static uint32_t fileWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
|
||||
uint32_t NumIOVecs) {
|
||||
|
||||
uint32_t I;
|
||||
FILE *File = (FILE *)This->WriterCtx;
|
||||
for (I = 0; I < NumIOVecs; I++) {
|
||||
if (fwrite(IOVecs[I].Data, IOVecs[I].ElmSize, IOVecs[I].NumElm, File) !=
|
||||
IOVecs[I].NumElm)
|
||||
return 1;
|
||||
if (IOVecs[I].Data) {
|
||||
if (fwrite(IOVecs[I].Data, IOVecs[I].ElmSize, IOVecs[I].NumElm, File) !=
|
||||
IOVecs[I].NumElm)
|
||||
return 1;
|
||||
} else {
|
||||
if (fseek(File, IOVecs[I].ElmSize * IOVecs[I].NumElm, SEEK_CUR) == -1)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -133,9 +137,10 @@ static void setupIOBuffer() {
|
|||
|
||||
/* Read profile data in \c ProfileFile and merge with in-memory
|
||||
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;
|
||||
char *ProfileBuffer;
|
||||
|
||||
|
@ -180,6 +185,8 @@ static int doProfileMerging(FILE *ProfileFile) {
|
|||
__llvm_profile_merge_from_buffer(ProfileBuffer, ProfileFileSize);
|
||||
(void)munmap(ProfileBuffer, ProfileFileSize);
|
||||
|
||||
*MergeDone = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -201,7 +208,7 @@ static void createProfileDir(const char *Filename) {
|
|||
* dumper. With profile merging enabled, each executable as well as any of
|
||||
* 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;
|
||||
int rc;
|
||||
|
||||
|
@ -210,8 +217,8 @@ static FILE *openFileForMerging(const char *ProfileFileName) {
|
|||
if (!ProfileFile)
|
||||
return NULL;
|
||||
|
||||
rc = doProfileMerging(ProfileFile);
|
||||
if (rc || COMPILER_RT_FTRUNCATE(ProfileFile, 0L) ||
|
||||
rc = doProfileMerging(ProfileFile, MergeDone);
|
||||
if (rc || (!*MergeDone && COMPILER_RT_FTRUNCATE(ProfileFile, 0L)) ||
|
||||
fseek(ProfileFile, 0L, SEEK_SET) == -1) {
|
||||
PROF_ERR("Profile Merging of file %s failed: %s\n", ProfileFileName,
|
||||
strerror(errno));
|
||||
|
@ -226,10 +233,11 @@ static int writeFile(const char *OutputName) {
|
|||
int RetVal;
|
||||
FILE *OutputFile;
|
||||
|
||||
int MergeDone = 0;
|
||||
if (!doMerging())
|
||||
OutputFile = fopen(OutputName, "ab");
|
||||
else
|
||||
OutputFile = openFileForMerging(OutputName);
|
||||
OutputFile = openFileForMerging(OutputName, &MergeDone);
|
||||
|
||||
if (!OutputFile)
|
||||
return -1;
|
||||
|
@ -238,7 +246,7 @@ static int writeFile(const char *OutputName) {
|
|||
setupIOBuffer();
|
||||
ProfDataWriter fileWriter;
|
||||
initFileWriter(&fileWriter, OutputFile);
|
||||
RetVal = lprofWriteData(&fileWriter, lprofGetVPDataReader());
|
||||
RetVal = lprofWriteData(&fileWriter, lprofGetVPDataReader(), MergeDone);
|
||||
|
||||
fclose(OutputFile);
|
||||
return RetVal;
|
||||
|
|
|
@ -102,7 +102,6 @@ int lprofBufferIOFlush(ProfBufferIO *BufferIO);
|
|||
* and profile data writer. */
|
||||
uint32_t lprofBufferWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
|
||||
uint32_t NumIOVecs);
|
||||
|
||||
void initBufferWriter(ProfDataWriter *BufferWriter, char *Buffer);
|
||||
|
||||
struct ValueProfData;
|
||||
|
@ -139,14 +138,17 @@ typedef struct VPDataReaderType {
|
|||
uint32_t N);
|
||||
} 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,
|
||||
const __llvm_profile_data *DataBegin,
|
||||
const __llvm_profile_data *DataEnd,
|
||||
const uint64_t *CountersBegin,
|
||||
const uint64_t *CountersEnd,
|
||||
VPDataReaderType *VPDataReader, const char *NamesBegin,
|
||||
const char *NamesEnd);
|
||||
const char *NamesEnd, int SkipNameDataWrite);
|
||||
|
||||
/* Merge value profile data pointed to by SrcValueProfData into
|
||||
* 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;
|
||||
for (I = 0; I < NumIOVecs; I++) {
|
||||
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;
|
||||
}
|
||||
return 0;
|
||||
|
@ -231,7 +232,8 @@ static int writeValueProfData(ProfDataWriter *Writer,
|
|||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY int lprofWriteData(ProfDataWriter *Writer,
|
||||
VPDataReaderType *VPDataReader) {
|
||||
VPDataReaderType *VPDataReader,
|
||||
int SkipNameDataWrite) {
|
||||
/* Match logic in __llvm_profile_write_buffer(). */
|
||||
const __llvm_profile_data *DataBegin = __llvm_profile_begin_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 *NamesEnd = __llvm_profile_end_names();
|
||||
return lprofWriteDataImpl(Writer, DataBegin, DataEnd, CountersBegin,
|
||||
CountersEnd, VPDataReader, NamesBegin, NamesEnd);
|
||||
CountersEnd, VPDataReader, NamesBegin, NamesEnd,
|
||||
SkipNameDataWrite);
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY int
|
||||
|
@ -248,7 +251,7 @@ lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin,
|
|||
const __llvm_profile_data *DataEnd,
|
||||
const uint64_t *CountersBegin, const uint64_t *CountersEnd,
|
||||
VPDataReaderType *VPDataReader, const char *NamesBegin,
|
||||
const char *NamesEnd) {
|
||||
const char *NamesEnd, int SkipNameDataWrite) {
|
||||
|
||||
/* Calculate size of sections. */
|
||||
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"
|
||||
|
||||
/* Write the data. */
|
||||
ProfDataIOVec IOVec[] = {{&Header, sizeof(__llvm_profile_header), 1},
|
||||
{DataBegin, sizeof(__llvm_profile_data), DataSize},
|
||||
{CountersBegin, sizeof(uint64_t), CountersSize},
|
||||
{NamesBegin, sizeof(uint8_t), NamesSize},
|
||||
{Zeroes, sizeof(uint8_t), Padding}};
|
||||
ProfDataIOVec IOVec[] = {
|
||||
{&Header, sizeof(__llvm_profile_header), 1},
|
||||
{DataBegin, sizeof(__llvm_profile_data), DataSize},
|
||||
{CountersBegin, sizeof(uint64_t), CountersSize},
|
||||
{SkipNameDataWrite ? NULL : NamesBegin, sizeof(uint8_t), NamesSize},
|
||||
{Zeroes, sizeof(uint8_t), Padding}};
|
||||
if (Writer->Write(Writer, IOVec, sizeof(IOVec) / sizeof(*IOVec)))
|
||||
return -1;
|
||||
|
||||
|
|
Loading…
Reference in New Issue