mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
Add --hot-func-list to llvm-profdata show for sample profiles
Summary: Add the --hot-func-list feature to llvm-profdata show for sample profiles. This feature prints a list of hot functions whose max sample count are above the 99% threshold, with their numbers of total samples, total samples percentage, max samples, entry samples, and their function names. Test Plan: Reviewers: wenlei, hoyFB Reviewed By: wenlei, hoyFB Subscribers: hoyFB, wenlei, weihe, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D82355
This commit is contained in:
parent
6be775e836
commit
4f72d6501a
@ -498,6 +498,21 @@ public:
|
||||
return CallsiteSamples;
|
||||
}
|
||||
|
||||
/// Return the maximum of sample counts in a function body including functions
|
||||
/// inlined in it.
|
||||
uint64_t getMaxCountInside() const {
|
||||
uint64_t MaxCount = 0;
|
||||
for (const auto &L : getBodySamples()) {
|
||||
MaxCount = std::max(MaxCount, L.second.getSamples());
|
||||
}
|
||||
for (const auto &C : getCallsiteSamples()) {
|
||||
for (const auto &F : C.second) {
|
||||
MaxCount = std::max(MaxCount, F.second.getMaxCountInside());
|
||||
}
|
||||
}
|
||||
return MaxCount;
|
||||
}
|
||||
|
||||
/// Merge the samples in \p Other into this one.
|
||||
/// Optionally scale samples by \p Weight.
|
||||
sampleprof_error merge(const FunctionSamples &Other, uint64_t Weight = 1) {
|
||||
|
@ -0,0 +1,41 @@
|
||||
_Z3bari:20301:1437
|
||||
1: 1437
|
||||
_Z3fooi:7711:610
|
||||
1: 610
|
||||
main:184019:0
|
||||
4: 534
|
||||
4.2: 534
|
||||
5: 1075
|
||||
5.1: 1075
|
||||
6: 2080
|
||||
7: 534
|
||||
9: 2300 _Z3bari:1471 _Z3fooi:631
|
||||
10: inline1:1000
|
||||
1: 1000
|
||||
10: inline2:2000
|
||||
1: 2000
|
||||
_Z3bazi:20305:1000
|
||||
1: 1000
|
||||
Func1:1523:169
|
||||
1: 169
|
||||
7: 563
|
||||
Func2:17043:1594
|
||||
1: 1594
|
||||
3: 1594
|
||||
6: 2009 Func1:150 Func3:1789
|
||||
13: 3105
|
||||
17: 3105
|
||||
19: 1594
|
||||
Func3:97401:3035
|
||||
1: 3035
|
||||
5: 7344
|
||||
9: 10640
|
||||
11: 10640
|
||||
15: 3035
|
||||
Func4:465:210
|
||||
1: 210
|
||||
Func5:6948:470
|
||||
1: 470
|
||||
3: 3507
|
||||
Func6:310:102
|
||||
1: 102
|
12
test/tools/llvm-profdata/sample-hot-func-list.test
Normal file
12
test/tools/llvm-profdata/sample-hot-func-list.test
Normal file
@ -0,0 +1,12 @@
|
||||
; RUN: llvm-profdata show --sample --hot-func-list %S/Inputs/sample-hot-func-list.proftext | FileCheck %s
|
||||
; CHECK: 8 out of 10 functions with profile (80.00%) are considered hot functions (max sample >= 470).
|
||||
; CHECK-NEXT: 355251 out of 356026 profile counts (99.78%) are from hot functions.
|
||||
; CHECK-NEXT: Total sample (%) Max sample Entry sample Function name
|
||||
; CHECK-NEXT: 184019 (51.69%) 2300 534 main
|
||||
; CHECK-NEXT: 97401 (27.36%) 10640 3035 Func3
|
||||
; CHECK-NEXT: 20305 (5.70%) 1000 1000 _Z3bazi
|
||||
; CHECK-NEXT: 20301 (5.70%) 1437 1437 _Z3bari
|
||||
; CHECK-NEXT: 17043 (4.79%) 3105 1594 Func2
|
||||
; CHECK-NEXT: 7711 (2.17%) 610 610 _Z3fooi
|
||||
; CHECK-NEXT: 6948 (1.95%) 3507 470 Func5
|
||||
; CHECK-NEXT: 1523 (0.43%) 563 169 Func1
|
@ -23,11 +23,12 @@
|
||||
#include "llvm/Support/Errc.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/FormattedStream.h"
|
||||
#include "llvm/Support/InitLLVM.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/Threading.h"
|
||||
#include "llvm/Support/ThreadPool.h"
|
||||
#include "llvm/Support/Threading.h"
|
||||
#include "llvm/Support/WithColor.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
@ -1026,11 +1027,142 @@ static void showSectionInfo(sampleprof::SampleProfileReader *Reader,
|
||||
}
|
||||
}
|
||||
|
||||
struct HotFuncInfo {
|
||||
StringRef FuncName;
|
||||
uint64_t TotalCount;
|
||||
double TotalCountPercent;
|
||||
uint64_t MaxCount;
|
||||
uint64_t EntryCount;
|
||||
|
||||
HotFuncInfo()
|
||||
: FuncName(), TotalCount(0), TotalCountPercent(0.0f), MaxCount(0),
|
||||
EntryCount(0) {}
|
||||
|
||||
HotFuncInfo(StringRef FN, uint64_t TS, double TSP, uint64_t MS, uint64_t ES)
|
||||
: FuncName(FN), TotalCount(TS), TotalCountPercent(TSP), MaxCount(MS),
|
||||
EntryCount(ES) {}
|
||||
};
|
||||
|
||||
// Print out detailed information about hot functions in PrintValues vector.
|
||||
// Users specify titles and offset of every columns through ColumnTitle and
|
||||
// ColumnOffset. The size of ColumnTitle and ColumnOffset need to be the same
|
||||
// and at least 4. Besides, users can optionally give a HotFuncMetric string to
|
||||
// print out or let it be an empty string.
|
||||
static void dumpHotFunctionList(const std::vector<std::string> &ColumnTitle,
|
||||
const std::vector<int> &ColumnOffset,
|
||||
const std::vector<HotFuncInfo> &PrintValues,
|
||||
uint64_t HotFuncCount, uint64_t TotalFuncCount,
|
||||
uint64_t HotProfCount, uint64_t TotalProfCount,
|
||||
const std::string &HotFuncMetric,
|
||||
raw_fd_ostream &OS) {
|
||||
assert(ColumnOffset.size() == ColumnTitle.size());
|
||||
assert(ColumnTitle.size() >= 4);
|
||||
assert(TotalFuncCount > 0);
|
||||
double TotalProfPercent = 0;
|
||||
if (TotalProfCount > 0)
|
||||
TotalProfPercent = ((double)HotProfCount) / TotalProfCount * 100;
|
||||
|
||||
formatted_raw_ostream FOS(OS);
|
||||
FOS << HotFuncCount << " out of " << TotalFuncCount
|
||||
<< " functions with profile ("
|
||||
<< format("%.2f%%", (((double)HotFuncCount) / TotalFuncCount * 100))
|
||||
<< ") are considered hot functions";
|
||||
if (!HotFuncMetric.empty())
|
||||
FOS << " (" << HotFuncMetric << ")";
|
||||
FOS << ".\n";
|
||||
FOS << HotProfCount << " out of " << TotalProfCount << " profile counts ("
|
||||
<< format("%.2f%%", TotalProfPercent) << ") are from hot functions.\n";
|
||||
|
||||
for (size_t I = 0; I < ColumnTitle.size(); ++I) {
|
||||
FOS.PadToColumn(ColumnOffset[I]);
|
||||
FOS << ColumnTitle[I];
|
||||
}
|
||||
FOS << "\n";
|
||||
|
||||
for (const auto &R : PrintValues) {
|
||||
FOS.PadToColumn(ColumnOffset[0]);
|
||||
FOS << R.TotalCount << " (" << format("%.2f%%", R.TotalCountPercent) << ")";
|
||||
FOS.PadToColumn(ColumnOffset[1]);
|
||||
FOS << R.MaxCount;
|
||||
FOS.PadToColumn(ColumnOffset[2]);
|
||||
FOS << R.EntryCount;
|
||||
FOS.PadToColumn(ColumnOffset[3]);
|
||||
FOS << R.FuncName << "\n";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
showHotFunctionList(const StringMap<sampleprof::FunctionSamples> &Profiles,
|
||||
ProfileSummary &PS, raw_fd_ostream &OS) {
|
||||
using namespace sampleprof;
|
||||
|
||||
const uint32_t HotFuncCutoff = 990000;
|
||||
auto &SummaryVector = PS.getDetailedSummary();
|
||||
uint64_t MinCountThreshold = 0;
|
||||
for (const auto &SummaryEntry : SummaryVector) {
|
||||
if (SummaryEntry.Cutoff == HotFuncCutoff) {
|
||||
MinCountThreshold = SummaryEntry.MinCount;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(MinCountThreshold != 0);
|
||||
|
||||
// Traverse all functions in the profile and keep only hot functions.
|
||||
// The following loop also calculates the sum of total samples of all
|
||||
// functions.
|
||||
std::multimap<uint64_t, std::pair<const FunctionSamples *, const uint64_t>,
|
||||
std::greater<uint64_t>>
|
||||
HotFunc;
|
||||
uint64_t ProfileTotalSample = 0;
|
||||
uint64_t HotFuncSample = 0;
|
||||
uint64_t HotFuncCount = 0;
|
||||
uint64_t MaxCount = 0;
|
||||
for (const auto &I : Profiles) {
|
||||
const auto &FuncProf = I.second;
|
||||
ProfileTotalSample += FuncProf.getTotalSamples();
|
||||
MaxCount = FuncProf.getMaxCountInside();
|
||||
|
||||
// MinCountThreshold is a block/line threshold computed for a given cutoff.
|
||||
// We intentionally compare the maximum sample count in a function with this
|
||||
// threshold to get an approximate threshold for hot functions.
|
||||
if (MaxCount >= MinCountThreshold) {
|
||||
HotFunc.emplace(FuncProf.getTotalSamples(),
|
||||
std::make_pair(&(I.second), MaxCount));
|
||||
HotFuncSample += FuncProf.getTotalSamples();
|
||||
++HotFuncCount;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> ColumnTitle{"Total sample (%)", "Max sample",
|
||||
"Entry sample", "Function name"};
|
||||
std::vector<int> ColumnOffset{0, 24, 42, 58};
|
||||
std::string Metric =
|
||||
std::string("max sample >= ") + std::to_string(MinCountThreshold);
|
||||
std::vector<HotFuncInfo> PrintValues;
|
||||
for (const auto &FuncPair : HotFunc) {
|
||||
const auto &FuncPtr = FuncPair.second.first;
|
||||
double TotalSamplePercent =
|
||||
(ProfileTotalSample > 0)
|
||||
? (FuncPtr->getTotalSamples() * 100.0) / ProfileTotalSample
|
||||
: 0;
|
||||
PrintValues.emplace_back(HotFuncInfo(
|
||||
FuncPtr->getFuncName(), FuncPtr->getTotalSamples(), TotalSamplePercent,
|
||||
FuncPair.second.second, FuncPtr->getEntrySamples()));
|
||||
}
|
||||
dumpHotFunctionList(ColumnTitle, ColumnOffset, PrintValues, HotFuncCount,
|
||||
Profiles.size(), HotFuncSample, ProfileTotalSample,
|
||||
Metric, OS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int showSampleProfile(const std::string &Filename, bool ShowCounts,
|
||||
bool ShowAllFunctions, bool ShowDetailedSummary,
|
||||
const std::string &ShowFunction,
|
||||
bool ShowProfileSymbolList,
|
||||
bool ShowSectionInfoOnly, raw_fd_ostream &OS) {
|
||||
bool ShowSectionInfoOnly, bool ShowHotFuncList,
|
||||
raw_fd_ostream &OS) {
|
||||
using namespace sampleprof;
|
||||
LLVMContext Context;
|
||||
auto ReaderOrErr = SampleProfileReader::create(Filename, Context);
|
||||
@ -1064,6 +1196,9 @@ static int showSampleProfile(const std::string &Filename, bool ShowCounts,
|
||||
PS.printDetailedSummary(OS);
|
||||
}
|
||||
|
||||
if (ShowHotFuncList)
|
||||
showHotFunctionList(Reader->getProfiles(), Reader->getSummary(), OS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1090,6 +1225,9 @@ static int show_main(int argc, const char *argv[]) {
|
||||
cl::desc(
|
||||
"Cutoff percentages (times 10000) for generating detailed summary"),
|
||||
cl::value_desc("800000,901000,999999"));
|
||||
cl::opt<bool> ShowHotFuncList(
|
||||
"hot-func-list", cl::init(false),
|
||||
cl::desc("Show profile summary of a list of hot functions"));
|
||||
cl::opt<bool> ShowAllFunctions("all-functions", cl::init(false),
|
||||
cl::desc("Details for every function"));
|
||||
cl::opt<bool> ShowCS("showcs", cl::init(false),
|
||||
@ -1153,7 +1291,8 @@ static int show_main(int argc, const char *argv[]) {
|
||||
else
|
||||
return showSampleProfile(Filename, ShowCounts, ShowAllFunctions,
|
||||
ShowDetailedSummary, ShowFunction,
|
||||
ShowProfileSymbolList, ShowSectionInfoOnly, OS);
|
||||
ShowProfileSymbolList, ShowSectionInfoOnly,
|
||||
ShowHotFuncList, OS);
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
|
Loading…
Reference in New Issue
Block a user