Change sample profile writer to make it deterministic.

Summary: This patch changes the function profile output order to be deterministic. In order to make it easier to understand, hottest functions (with most total samples) is ordered first.

Reviewers: dnovillo, davidxl

Reviewed By: dnovillo

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D33111

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@302851 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dehao Chen 2017-05-11 23:43:44 +00:00
parent 7b29966a93
commit e26e940120
3 changed files with 43 additions and 17 deletions

View File

@ -43,16 +43,7 @@ public:
/// Write all the sample profiles in the given map of samples.
///
/// \returns status code of the file update operation.
std::error_code write(const StringMap<FunctionSamples> &ProfileMap) {
if (std::error_code EC = writeHeader(ProfileMap))
return EC;
for (const auto &I : ProfileMap) {
const FunctionSamples &Profile = I.second;
if (std::error_code EC = write(Profile))
return EC;
}
return sampleprof_error::success;
}
std::error_code write(const StringMap<FunctionSamples> &ProfileMap);
raw_ostream &getOutputStream() { return *OutputStream; }

View File

@ -29,6 +29,7 @@
#include <algorithm>
#include <cstdint>
#include <memory>
#include <set>
#include <system_error>
#include <utility>
#include <vector>
@ -36,6 +37,32 @@
using namespace llvm;
using namespace sampleprof;
std::error_code
SampleProfileWriter::write(const StringMap<FunctionSamples> &ProfileMap) {
if (std::error_code EC = writeHeader(ProfileMap))
return EC;
// Sort the ProfileMap by total samples.
typedef std::pair<StringRef, const FunctionSamples *> NameFunctionSamples;
std::vector<NameFunctionSamples> V;
for (const auto &I : ProfileMap)
V.push_back(std::make_pair(I.getKey(), &I.second));
std::stable_sort(
V.begin(), V.end(),
[](const NameFunctionSamples &A, const NameFunctionSamples &B) {
if (A.second->getTotalSamples() == B.second->getTotalSamples())
return A.first > B.first;
return A.second->getTotalSamples() > B.second->getTotalSamples();
});
for (const auto &I : V) {
if (std::error_code EC = write(*I.second))
return EC;
}
return sampleprof_error::success;
}
/// \brief Write samples to a text file.
///
/// Note: it may be tempting to implement this in terms of
@ -97,8 +124,7 @@ std::error_code SampleProfileWriterBinary::writeNameIdx(StringRef FName) {
}
void SampleProfileWriterBinary::addName(StringRef FName) {
auto NextIdx = NameTable.size();
NameTable.insert(std::make_pair(FName, NextIdx));
NameTable.insert(std::make_pair(FName, 0));
}
void SampleProfileWriterBinary::addNames(const FunctionSamples &S) {
@ -136,10 +162,18 @@ std::error_code SampleProfileWriterBinary::writeHeader(
addNames(I.second);
}
// Sort the names to make NameTable is deterministic.
std::set<StringRef> V;
for (const auto &I : NameTable)
V.insert(I.first);
int i = 0;
for (const StringRef &N : V)
NameTable[N] = i++;
// Write out the name table.
encodeULEB128(NameTable.size(), OS);
for (auto N : NameTable) {
OS << N.first;
for (auto N : V) {
OS << N;
encodeULEB128(0, OS);
}
return sampleprof_error::success;

View File

@ -25,9 +25,10 @@ RUN: diff %t-binary %t-text
counters have doubled.
RUN: llvm-profdata merge --sample %p/Inputs/sample-profile.proftext -o %t-binprof
RUN: llvm-profdata merge --sample --text %p/Inputs/sample-profile.proftext %t-binprof -o - | FileCheck %s --check-prefix=MERGE1
MERGE1-DAG: main:368038:0
MERGE1-DAG: 9: 4128 _Z3fooi:1262 _Z3bari:2942
MERGE1-DAG: _Z3fooi:15422:1220
MERGE1: main:368038:0
MERGE1: 9: 4128 _Z3fooi:1262 _Z3bari:2942
MERGE1: _Z3bari:40602:2874
MERGE1: _Z3fooi:15422:1220
5- Detect invalid text encoding (e.g. instrumentation profile text format).
RUN: not llvm-profdata show --sample %p/Inputs/foo3bar3-1.proftext 2>&1 | FileCheck %s --check-prefix=BADTEXT