diff --git a/llvm/include/llvm/ProfileData/RawMemProfReader.h b/llvm/include/llvm/ProfileData/RawMemProfReader.h --- a/llvm/include/llvm/ProfileData/RawMemProfReader.h +++ b/llvm/include/llvm/ProfileData/RawMemProfReader.h @@ -38,8 +38,6 @@ class RawMemProfReader { public: - RawMemProfReader(std::unique_ptr DataBuffer) - : DataBuffer(std::move(DataBuffer)) {} RawMemProfReader(const RawMemProfReader &) = delete; RawMemProfReader &operator=(const RawMemProfReader &) = delete; @@ -103,12 +101,12 @@ } private: - RawMemProfReader(std::unique_ptr DataBuffer, - object::OwningBinary &&Bin, bool KeepName) - : DataBuffer(std::move(DataBuffer)), Binary(std::move(Bin)), - KeepSymbolName(KeepName) {} - Error initialize(); - Error readRawProfile(); + RawMemProfReader(object::OwningBinary &&Bin, bool KeepName) + : Binary(std::move(Bin)), KeepSymbolName(KeepName) {} + // Initializes the RawMemProfReader with the contents in `DataBuffer`. + Error initialize(std::unique_ptr DataBuffer); + // Read and parse the contents of the `DataBuffer` as a binary format profile. + Error readRawProfile(std::unique_ptr 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 @@ } 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 DataBuffer; object::OwningBinary Binary; std::unique_ptr Symbolizer; diff --git a/llvm/lib/ProfileData/RawMemProfReader.cpp b/llvm/lib/ProfileData/RawMemProfReader.cpp --- a/llvm/lib/ProfileData/RawMemProfReader.cpp +++ b/llvm/lib/ProfileData/RawMemProfReader.cpp @@ -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 inline T alignedRead(const char *Ptr) { static_assert(std::is_pod::value, "Not a pod type."); assert(reinterpret_cast(Ptr) % sizeof(T) == 0 && "Unaligned Read"); return *reinterpret_cast(Ptr); } -Summary computeSummary(const char *Start) { - auto *H = reinterpret_cast(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(instrprof_error::bad_magic); @@ -196,9 +174,9 @@ } // Use new here since constructor is private. - std::unique_ptr Reader(new RawMemProfReader( - std::move(Buffer), std::move(BinaryOr.get()), KeepName)); - if (Error E = Reader->initialize()) { + std::unique_ptr 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 @@ } 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::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(Next); - Next += H->TotalSize; - } -} - -Error RawMemProfReader::initialize() { +Error RawMemProfReader::initialize(std::unique_ptr DataBuffer) { const StringRef FileName = Binary.getBinary()->getFileName(); auto *ElfObject = dyn_cast(Binary.getBinary()); @@ -283,7 +253,7 @@ 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 @@ return Error::success(); } -Error RawMemProfReader::readRawProfile() { +Error RawMemProfReader::readRawProfile( + std::unique_ptr DataBuffer) { const char *Next = DataBuffer->getBufferStart(); while (Next < DataBuffer->getBufferEnd()) { diff --git a/llvm/test/tools/llvm-profdata/memprof-basic.test b/llvm/test/tools/llvm-profdata/memprof-basic.test --- a/llvm/test/tools/llvm-profdata/memprof-basic.test +++ b/llvm/test/tools/llvm-profdata/memprof-basic.test @@ -36,14 +36,13 @@ 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]+}} diff --git a/llvm/test/tools/llvm-profdata/memprof-inline.test b/llvm/test/tools/llvm-profdata/memprof-inline.test --- a/llvm/test/tools/llvm-profdata/memprof-inline.test +++ b/llvm/test/tools/llvm-profdata/memprof-inline.test @@ -38,13 +38,12 @@ 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 diff --git a/llvm/test/tools/llvm-profdata/memprof-multi.test b/llvm/test/tools/llvm-profdata/memprof-multi.test --- a/llvm/test/tools/llvm-profdata/memprof-multi.test +++ b/llvm/test/tools/llvm-profdata/memprof-multi.test @@ -37,18 +37,18 @@ 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