[llvm] 6a7bbf7 - [memprof][NFC] Free symbolizer memory eagerly (#75849)

via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 18 20:50:12 PST 2023


Author: Teresa Johnson
Date: 2023-12-18T20:50:08-08:00
New Revision: 6a7bbf712df5637a93dbc4f918e7a69e23aa917c

URL: https://github.com/llvm/llvm-project/commit/6a7bbf712df5637a93dbc4f918e7a69e23aa917c
DIFF: https://github.com/llvm/llvm-project/commit/6a7bbf712df5637a93dbc4f918e7a69e23aa917c.diff

LOG: [memprof][NFC] Free symbolizer memory eagerly (#75849)

Move the ownership of the symbolizer into symbolizeAndFilterStackFrames
so that it is freed on exit, when we are done with it, to reduce peak
memory in the reader. This reduces about 9G from the peak for one large
profile.

Added: 
    

Modified: 
    llvm/include/llvm/ProfileData/RawMemProfReader.h
    llvm/lib/ProfileData/RawMemProfReader.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ProfileData/RawMemProfReader.h b/llvm/include/llvm/ProfileData/RawMemProfReader.h
index 796183aacc7237..6aa5caec65f791 100644
--- a/llvm/include/llvm/ProfileData/RawMemProfReader.h
+++ b/llvm/include/llvm/ProfileData/RawMemProfReader.h
@@ -147,14 +147,14 @@ class RawMemProfReader final : public MemProfReader {
                    llvm::SmallVectorImpl<SegmentEntry> &Seg,
                    llvm::MapVector<uint64_t, MemInfoBlock> &Prof,
                    CallStackMap &SM, bool KeepName = false)
-      : Symbolizer(std::move(Sym)), SegmentInfo(Seg.begin(), Seg.end()),
-        CallstackProfileData(Prof), StackMap(SM), KeepSymbolName(KeepName) {
+      : SegmentInfo(Seg.begin(), Seg.end()), CallstackProfileData(Prof),
+        StackMap(SM), KeepSymbolName(KeepName) {
     // We don't call initialize here since there is no raw profile to read. The
     // test should pass in the raw profile as structured data.
 
     // If there is an error here then the mock symbolizer has not been
     // initialized properly.
-    if (Error E = symbolizeAndFilterStackFrames())
+    if (Error E = symbolizeAndFilterStackFrames(std::move(Sym)))
       report_fatal_error(std::move(E));
     if (Error E = mapRawProfileToRecords())
       report_fatal_error(std::move(E));
@@ -173,7 +173,8 @@ class RawMemProfReader final : public MemProfReader {
   // 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
   // the entire callstack is pruned, we drop the entry from the profile.
-  Error symbolizeAndFilterStackFrames();
+  Error symbolizeAndFilterStackFrames(
+      std::unique_ptr<llvm::symbolize::SymbolizableModule> Symbolizer);
   // Construct memprof records for each function and store it in the
   // `FunctionProfileData` map. A function may have allocation profile data or
   // callsite data or both.
@@ -183,8 +184,6 @@ class RawMemProfReader final : public MemProfReader {
 
   // The profiled binary.
   object::OwningBinary<object::Binary> Binary;
-  // A symbolizer to translate virtual addresses to code locations.
-  std::unique_ptr<llvm::symbolize::SymbolizableModule> Symbolizer;
   // The preferred load address of the executable segment.
   uint64_t PreferredTextSegmentAddress = 0;
   // The base address of the text segment in the process during profiling.

diff  --git a/llvm/lib/ProfileData/RawMemProfReader.cpp b/llvm/lib/ProfileData/RawMemProfReader.cpp
index af2db8d61179a3..0e2b8668bab72c 100644
--- a/llvm/lib/ProfileData/RawMemProfReader.cpp
+++ b/llvm/lib/ProfileData/RawMemProfReader.cpp
@@ -336,6 +336,13 @@ Error RawMemProfReader::initialize(std::unique_ptr<MemoryBuffer> DataBuffer) {
                                           inconvertibleErrorCode()),
                   FileName);
 
+  // Process the raw profile.
+  if (Error E = readRawProfile(std::move(DataBuffer)))
+    return E;
+
+  if (Error E = setupForSymbolization())
+    return E;
+
   auto *Object = cast<object::ObjectFile>(Binary.getBinary());
   std::unique_ptr<DIContext> Context = DWARFContext::create(
       *Object, DWARFContext::ProcessDebugRelocations::Process);
@@ -344,16 +351,13 @@ Error RawMemProfReader::initialize(std::unique_ptr<MemoryBuffer> DataBuffer) {
       Object, std::move(Context), /*UntagAddresses=*/false);
   if (!SOFOr)
     return report(SOFOr.takeError(), FileName);
-  Symbolizer = std::move(SOFOr.get());
-
-  // Process the raw profile.
-  if (Error E = readRawProfile(std::move(DataBuffer)))
-    return E;
-
-  if (Error E = setupForSymbolization())
-    return E;
+  auto Symbolizer = std::move(SOFOr.get());
 
-  if (Error E = symbolizeAndFilterStackFrames())
+  // The symbolizer ownership is moved into symbolizeAndFilterStackFrames so
+  // that it is freed automatically at the end, when it is no longer used. This
+  // reduces peak memory since it won't be live while also mapping the raw
+  // profile into records afterwards.
+  if (Error E = symbolizeAndFilterStackFrames(std::move(Symbolizer)))
     return E;
 
   return mapRawProfileToRecords();
@@ -469,7 +473,8 @@ Error RawMemProfReader::mapRawProfileToRecords() {
   return Error::success();
 }
 
-Error RawMemProfReader::symbolizeAndFilterStackFrames() {
+Error RawMemProfReader::symbolizeAndFilterStackFrames(
+    std::unique_ptr<llvm::symbolize::SymbolizableModule> Symbolizer) {
   // The specifier to use when symbolization is requested.
   const DILineInfoSpecifier Specifier(
       DILineInfoSpecifier::FileLineInfoKind::RawValue,


        


More information about the llvm-commits mailing list