forked from OSchip/llvm-project
[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:
parent
fe0f2c1e99
commit
962db7de84
|
@ -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;
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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]+}}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue