[memprof] Update summary output.

Update the YAML format print out of the profile to include a summary
instead of displaying the headers in the raw file buffer. This allows us
to release the raw buffer early saving memory.

Reviewed By: tejohnson

Differential Revision: https://reviews.llvm.org/D126834
This commit is contained in:
Snehasish Kumar 2022-06-01 22:20:53 +00:00
parent fe0f2c1e99
commit 962db7de84
5 changed files with 51 additions and 88 deletions

View File

@ -38,8 +38,6 @@ using CallStackMap = llvm::DenseMap<uint64_t, llvm::SmallVector<uint64_t>>;
class RawMemProfReader {
public:
RawMemProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
: DataBuffer(std::move(DataBuffer)) {}
RawMemProfReader(const RawMemProfReader &) = delete;
RawMemProfReader &operator=(const RawMemProfReader &) = delete;
@ -103,12 +101,12 @@ public:
}
private:
RawMemProfReader(std::unique_ptr<MemoryBuffer> DataBuffer,
object::OwningBinary<object::Binary> &&Bin, bool KeepName)
: DataBuffer(std::move(DataBuffer)), Binary(std::move(Bin)),
KeepSymbolName(KeepName) {}
Error initialize();
Error readRawProfile();
RawMemProfReader(object::OwningBinary<object::Binary> &&Bin, bool KeepName)
: Binary(std::move(Bin)), KeepSymbolName(KeepName) {}
// Initializes the RawMemProfReader with the contents in `DataBuffer`.
Error initialize(std::unique_ptr<MemoryBuffer> DataBuffer);
// Read and parse the contents of the `DataBuffer` as a binary format profile.
Error readRawProfile(std::unique_ptr<MemoryBuffer> DataBuffer);
// Symbolize and cache all the virtual addresses we encounter in the
// callstacks from the raw profile. Also prune callstack frames which we can't
// symbolize or those that belong to the runtime. For profile entries where
@ -127,11 +125,7 @@ private:
}
object::SectionedAddress getModuleOffset(uint64_t VirtualAddress);
// Prints aggregate counts for each raw profile parsed from the DataBuffer in
// YAML format.
void printSummaries(raw_ostream &OS) const;
std::unique_ptr<MemoryBuffer> DataBuffer;
object::OwningBinary<object::Binary> Binary;
std::unique_ptr<llvm::symbolize::SymbolizableModule> Symbolizer;

View File

@ -36,34 +36,12 @@
namespace llvm {
namespace memprof {
namespace {
struct Summary {
uint64_t Version;
uint64_t TotalSizeBytes;
uint64_t NumSegments;
uint64_t NumMIBInfo;
uint64_t NumStackOffsets;
};
template <class T = uint64_t> inline T alignedRead(const char *Ptr) {
static_assert(std::is_pod<T>::value, "Not a pod type.");
assert(reinterpret_cast<size_t>(Ptr) % sizeof(T) == 0 && "Unaligned Read");
return *reinterpret_cast<const T *>(Ptr);
}
Summary computeSummary(const char *Start) {
auto *H = reinterpret_cast<const Header *>(Start);
// Check alignment while reading the number of items in each section.
return Summary{
H->Version,
H->TotalSize,
alignedRead(Start + H->SegmentOffset),
alignedRead(Start + H->MIBOffset),
alignedRead(Start + H->StackOffset),
};
}
Error checkBuffer(const MemoryBuffer &Buffer) {
if (!RawMemProfReader::hasFormat(Buffer))
return make_error<InstrProfError>(instrprof_error::bad_magic);
@ -196,9 +174,9 @@ RawMemProfReader::create(const Twine &Path, const StringRef ProfiledBinary,
}
// Use new here since constructor is private.
std::unique_ptr<RawMemProfReader> Reader(new RawMemProfReader(
std::move(Buffer), std::move(BinaryOr.get()), KeepName));
if (Error E = Reader->initialize()) {
std::unique_ptr<RawMemProfReader> Reader(
new RawMemProfReader(std::move(BinaryOr.get()), KeepName));
if (Error E = Reader->initialize(std::move(Buffer))) {
return std::move(E);
}
return std::move(Reader);
@ -223,11 +201,22 @@ bool RawMemProfReader::hasFormat(const MemoryBuffer &Buffer) {
}
void RawMemProfReader::printYAML(raw_ostream &OS) {
uint64_t NumAllocFunctions = 0, NumMibInfo = 0;
for (const auto &KV : FunctionProfileData) {
const size_t NumAllocSites = KV.second.AllocSites.size();
if (NumAllocSites > 0) {
NumAllocFunctions++;
NumMibInfo += NumAllocSites;
}
}
OS << "MemprofProfile:\n";
// TODO: Update printSummaries to print out the data after the profile has
// been symbolized and pruned. We can parse some raw profile characteristics
// from the data buffer for additional information.
printSummaries(OS);
OS << " Summary:\n";
OS << " Version: " << MEMPROF_RAW_VERSION << "\n";
OS << " NumSegments: " << SegmentInfo.size() << "\n";
OS << " NumMibInfo: " << NumMibInfo << "\n";
OS << " NumAllocFunctions: " << NumAllocFunctions << "\n";
OS << " NumStackOffsets: " << StackMap.size() << "\n";
// Print out the merged contents of the profiles.
OS << " Records:\n";
for (const auto &Entry : *this) {
@ -237,26 +226,7 @@ void RawMemProfReader::printYAML(raw_ostream &OS) {
}
}
void RawMemProfReader::printSummaries(raw_ostream &OS) const {
const char *Next = DataBuffer->getBufferStart();
while (Next < DataBuffer->getBufferEnd()) {
auto Summary = computeSummary(Next);
OS << " -\n";
OS << " Header:\n";
OS << " Version: " << Summary.Version << "\n";
OS << " TotalSizeBytes: " << Summary.TotalSizeBytes << "\n";
OS << " NumSegments: " << Summary.NumSegments << "\n";
OS << " NumMibInfo: " << Summary.NumMIBInfo << "\n";
OS << " NumStackOffsets: " << Summary.NumStackOffsets << "\n";
// TODO: Print the build ids once we can record them using the
// sanitizer_procmaps library for linux.
auto *H = reinterpret_cast<const Header *>(Next);
Next += H->TotalSize;
}
}
Error RawMemProfReader::initialize() {
Error RawMemProfReader::initialize(std::unique_ptr<MemoryBuffer> DataBuffer) {
const StringRef FileName = Binary.getBinary()->getFileName();
auto *ElfObject = dyn_cast<object::ELFObjectFileBase>(Binary.getBinary());
@ -283,7 +253,7 @@ Error RawMemProfReader::initialize() {
return report(SOFOr.takeError(), FileName);
Symbolizer = std::move(SOFOr.get());
if (Error E = readRawProfile())
if (Error E = readRawProfile(std::move(DataBuffer)))
return E;
if (Error E = symbolizeAndFilterStackFrames())
@ -452,7 +422,8 @@ Error RawMemProfReader::symbolizeAndFilterStackFrames() {
return Error::success();
}
Error RawMemProfReader::readRawProfile() {
Error RawMemProfReader::readRawProfile(
std::unique_ptr<MemoryBuffer> DataBuffer) {
const char *Next = DataBuffer->getBufferStart();
while (Next < DataBuffer->getBufferEnd()) {

View File

@ -36,14 +36,13 @@ RUN: llvm-profdata show --memory %p/Inputs/basic.memprofraw --profiled-binary %p
We expect 2 MIB entries, 1 each for the malloc calls in the program. Any
additional allocations which do not originate from the main binary are pruned.
CHECK: MemprofProfile:
CHECK-NEXT: -
CHECK-NEXT: Header:
CHECK: MemprofProfile:
CHECK-NEXT: Summary:
CHECK-NEXT: Version: 1
CHECK-NEXT: TotalSizeBytes: 1016
CHECK-NEXT: NumSegments: 9
CHECK-NEXT: NumMibInfo: 3
CHECK-NEXT: NumStackOffsets: 3
CHECK-NEXT: NumMibInfo: 2
CHECK-NEXT: NumAllocFunctions: 1
CHECK-NEXT: NumStackOffsets: 2
CHECK-NEXT: Records:
CHECK-NEXT: -
CHECK-NEXT: FunctionGUID: {{[0-9]+}}

View File

@ -38,13 +38,12 @@ env MEMPROF_OPTIONS=log_path=stdout ./memprof-inline.exe > inline.memprofraw
RUN: llvm-profdata show --memory %p/Inputs/inline.memprofraw --profiled-binary %p/Inputs/inline.memprofexe | FileCheck %s
CHECK: MemprofProfile:
CHECK-NEXT: -
CHECK-NEXT: Header:
CHECK-NEXT: Summary:
CHECK-NEXT: Version: 1
CHECK-NEXT: TotalSizeBytes: 880
CHECK-NEXT: NumSegments: 9
CHECK-NEXT: NumMibInfo: 2
CHECK-NEXT: NumStackOffsets: 2
CHECK-NEXT: NumAllocFunctions: 2
CHECK-NEXT: NumStackOffsets: 1
CHECK-NEXT: Records:
CHECK-NEXT: -
CHECK-NEXT: FunctionGUID: 15505678318020221912

View File

@ -37,18 +37,18 @@ RUN: llvm-profdata show --memory %p/Inputs/multi.memprofraw --profiled-binary %p
We expect 2 MIB entries, 1 each for the malloc calls in the program.
CHECK: MemprofProfile:
CHECK-NEXT: -
CHECK-NEXT: Header:
CHECK-NEXT: Version: 1
CHECK-NEXT: TotalSizeBytes: 864
CHECK-NEXT: NumSegments: 9
CHECK-NEXT: NumMibInfo: 2
CHECK-NEXT: NumStackOffsets: 2
CHECK-NEXT: -
CHECK-NEXT: Header:
CHECK-NEXT: Version: 1
CHECK-NEXT: TotalSizeBytes: 864
CHECK-NEXT: NumSegments: 9
CHECK-NEXT: NumMibInfo: 2
CHECK-NEXT: NumStackOffsets: 2
CHECK: MemprofProfile:
CHECK-NEXT: Summary:
CHECK-NEXT: Version: 1
CHECK-NEXT: NumSegments: 9
CHECK-NEXT: NumMibInfo: 2
CHECK-NEXT: NumAllocFunctions: 1
CHECK-NEXT: NumStackOffsets: 2
CHECK: SymbolName: main
CHECK-NEXT: LineOffset: 1
CHECK-NEXT: Column: 21
CHECK: SymbolName: main
CHECK-NEXT: LineOffset: 5
CHECK-NEXT: Column: 15