Skip to content

Commit 17f6cba

Browse files
committed
[llvm-profgen] Add process filter for perf reader
For profile generation, we need to filter raw perf samples for binary of interest. Sometimes binary name along isn't enough as we can have binary of the same name running in the system. This change adds a process id filter to allow users to further disambiguiate the input raw samples. Differential Revision: https://reviews.llvm.org/D123869
1 parent f4085c5 commit 17f6cba

File tree

3 files changed

+39
-16
lines changed

3 files changed

+39
-16
lines changed

llvm/tools/llvm-profgen/PerfReader.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,8 @@ bool VirtualUnwinder::unwind(const PerfSample *Sample, uint64_t Repeat) {
341341
}
342342

343343
std::unique_ptr<PerfReaderBase>
344-
PerfReaderBase::create(ProfiledBinary *Binary, PerfInputFile &PerfInput) {
344+
PerfReaderBase::create(ProfiledBinary *Binary, PerfInputFile &PerfInput,
345+
Optional<uint32_t> PIDFilter) {
345346
std::unique_ptr<PerfReaderBase> PerfReader;
346347

347348
if (PerfInput.Format == PerfFormat::UnsymbolizedProfile) {
@@ -352,26 +353,28 @@ PerfReaderBase::create(ProfiledBinary *Binary, PerfInputFile &PerfInput) {
352353

353354
// For perf data input, we need to convert them into perf script first.
354355
if (PerfInput.Format == PerfFormat::PerfData)
355-
PerfInput = PerfScriptReader::convertPerfDataToTrace(Binary, PerfInput);
356+
PerfInput =
357+
PerfScriptReader::convertPerfDataToTrace(Binary, PerfInput, PIDFilter);
356358

357359
assert((PerfInput.Format == PerfFormat::PerfScript) &&
358360
"Should be a perfscript!");
359361

360362
PerfInput.Content =
361363
PerfScriptReader::checkPerfScriptType(PerfInput.InputFile);
362364
if (PerfInput.Content == PerfContent::LBRStack) {
363-
PerfReader.reset(new HybridPerfReader(Binary, PerfInput.InputFile));
365+
PerfReader.reset(
366+
new HybridPerfReader(Binary, PerfInput.InputFile, PIDFilter));
364367
} else if (PerfInput.Content == PerfContent::LBR) {
365-
PerfReader.reset(new LBRPerfReader(Binary, PerfInput.InputFile));
368+
PerfReader.reset(new LBRPerfReader(Binary, PerfInput.InputFile, PIDFilter));
366369
} else {
367370
exitWithError("Unsupported perfscript!");
368371
}
369372

370373
return PerfReader;
371374
}
372375

373-
PerfInputFile PerfScriptReader::convertPerfDataToTrace(ProfiledBinary *Binary,
374-
PerfInputFile &File) {
376+
PerfInputFile PerfScriptReader::convertPerfDataToTrace(
377+
ProfiledBinary *Binary, PerfInputFile &File, Optional<uint32_t> PIDFilter) {
375378
StringRef PerfData = File.InputFile;
376379
// Run perf script to retrieve PIDs matching binary we're interested in.
377380
auto PerfExecutable = sys::Process::FindInEnvPath("PATH", "perf");
@@ -397,7 +400,7 @@ PerfInputFile PerfScriptReader::convertPerfDataToTrace(ProfiledBinary *Binary,
397400
if (isMMap2Event(TraceIt.getCurrentLine()) &&
398401
extractMMap2EventForBinary(Binary, TraceIt.getCurrentLine(), MMap)) {
399402
auto It = PIDSet.emplace(MMap.PID);
400-
if (It.second) {
403+
if (It.second && (!PIDFilter || MMap.PID == *PIDFilter)) {
401404
if (!PIDs.empty()) {
402405
PIDs.append(",");
403406
}
@@ -426,6 +429,10 @@ void PerfScriptReader::updateBinaryAddress(const MMapEvent &Event) {
426429
if (Binary->getName() != BinaryName)
427430
return;
428431

432+
// Drop the event if process does not match pid filter
433+
if (PIDFilter && Event.PID != *PIDFilter)
434+
return;
435+
429436
// Drop the event if its image is loaded at the same address
430437
if (Event.Address == Binary->getBaseAddress()) {
431438
Binary->setIsLoadedByMMap(true);

llvm/tools/llvm-profgen/PerfReader.h

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "llvm/Support/Casting.h"
1414
#include "llvm/Support/CommandLine.h"
1515
#include "llvm/Support/Regex.h"
16+
#include <bits/stdint-uintn.h>
1617
#include <cstdint>
1718
#include <fstream>
1819
#include <list>
@@ -544,7 +545,8 @@ class PerfReaderBase {
544545
};
545546
virtual ~PerfReaderBase() = default;
546547
static std::unique_ptr<PerfReaderBase> create(ProfiledBinary *Binary,
547-
PerfInputFile &PerfInput);
548+
PerfInputFile &PerfInput,
549+
Optional<uint32_t> PIDFilter);
548550

549551
// Entry of the reader to parse multiple perf traces
550552
virtual void parsePerfTraces() = 0;
@@ -568,14 +570,16 @@ class PerfReaderBase {
568570
// Read perf script to parse the events and samples.
569571
class PerfScriptReader : public PerfReaderBase {
570572
public:
571-
PerfScriptReader(ProfiledBinary *B, StringRef PerfTrace)
572-
: PerfReaderBase(B, PerfTrace){};
573+
PerfScriptReader(ProfiledBinary *B, StringRef PerfTrace,
574+
Optional<uint32_t> PID)
575+
: PerfReaderBase(B, PerfTrace), PIDFilter(PID){};
573576

574577
// Entry of the reader to parse multiple perf traces
575578
virtual void parsePerfTraces() override;
576579
// Generate perf script from perf data
577580
static PerfInputFile convertPerfDataToTrace(ProfiledBinary *Binary,
578-
PerfInputFile &File);
581+
PerfInputFile &File,
582+
Optional<uint32_t> PIDFilter);
579583
// Extract perf script type by peaking at the input
580584
static PerfContent checkPerfScriptType(StringRef FileName);
581585

@@ -635,6 +639,8 @@ class PerfScriptReader : public PerfReaderBase {
635639
AggregatedCounter AggregatedSamples;
636640
// Keep track of all invalid return addresses
637641
std::set<uint64_t> InvalidReturnAddresses;
642+
// PID for the process of interest
643+
Optional<uint32_t> PIDFilter;
638644
};
639645

640646
/*
@@ -645,8 +651,9 @@ class PerfScriptReader : public PerfReaderBase {
645651
*/
646652
class LBRPerfReader : public PerfScriptReader {
647653
public:
648-
LBRPerfReader(ProfiledBinary *Binary, StringRef PerfTrace)
649-
: PerfScriptReader(Binary, PerfTrace){};
654+
LBRPerfReader(ProfiledBinary *Binary, StringRef PerfTrace,
655+
Optional<uint32_t> PID)
656+
: PerfScriptReader(Binary, PerfTrace, PID){};
650657
// Parse the LBR only sample.
651658
virtual void parseSample(TraceStream &TraceIt, uint64_t Count) override;
652659
};
@@ -662,8 +669,9 @@ class LBRPerfReader : public PerfScriptReader {
662669
*/
663670
class HybridPerfReader : public PerfScriptReader {
664671
public:
665-
HybridPerfReader(ProfiledBinary *Binary, StringRef PerfTrace)
666-
: PerfScriptReader(Binary, PerfTrace){};
672+
HybridPerfReader(ProfiledBinary *Binary, StringRef PerfTrace,
673+
Optional<uint32_t> PID)
674+
: PerfScriptReader(Binary, PerfTrace, PID){};
667675
// Parse the hybrid sample including the call and LBR line
668676
void parseSample(TraceStream &TraceIt, uint64_t Count) override;
669677
void generateUnsymbolizedProfile() override;

llvm/tools/llvm-profgen/llvm-profgen.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ static cl::opt<std::string>
6060
cl::desc("Path of profiled executable binary."),
6161
cl::cat(ProfGenCategory));
6262

63+
static cl::opt<uint32_t>
64+
ProcessId("pid", cl::value_desc("process Id"), cl::ZeroOrMore, cl::init(0),
65+
cl::desc("Process Id for the profiled executable binary."),
66+
cl::cat(ProfGenCategory));
67+
6368
static cl::opt<std::string> DebugBinPath(
6469
"debug-binary", cl::value_desc("debug-binary"), cl::ZeroOrMore,
6570
cl::desc("Path of debug info binary, llvm-profgen will load the DWARF info "
@@ -168,9 +173,12 @@ int main(int argc, const char *argv[]) {
168173
Generator->generateProfile();
169174
Generator->write();
170175
} else {
176+
Optional<uint32_t> PIDFilter;
177+
if (ProcessId.getNumOccurrences())
178+
PIDFilter = ProcessId;
171179
PerfInputFile PerfFile = getPerfInputFile();
172180
std::unique_ptr<PerfReaderBase> Reader =
173-
PerfReaderBase::create(Binary.get(), PerfFile);
181+
PerfReaderBase::create(Binary.get(), PerfFile, PIDFilter);
174182
// Parse perf events and samples
175183
Reader->parsePerfTraces();
176184

0 commit comments

Comments
 (0)