[llvm] [memprof][NFC] Free symbolizer memory eagerly (PR #75849)

Teresa Johnson via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 18 12:08:19 PST 2023


https://github.com/teresajohnson created https://github.com/llvm/llvm-project/pull/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.


>From 06512babde178a8ca7704217a0f7879316a2e9bb Mon Sep 17 00:00:00 2001
From: Teresa Johnson <tejohnson at google.com>
Date: Mon, 18 Dec 2023 12:06:46 -0800
Subject: [PATCH] [memprof][NFC] Free symbolizer memory eagerly

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.
---
 llvm/include/llvm/ProfileData/RawMemProfReader.h | 11 +++++------
 llvm/lib/ProfileData/RawMemProfReader.cpp        | 11 ++++++++---
 2 files changed, 13 insertions(+), 9 deletions(-)

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..42fd5a20806936 100644
--- a/llvm/lib/ProfileData/RawMemProfReader.cpp
+++ b/llvm/lib/ProfileData/RawMemProfReader.cpp
@@ -344,7 +344,7 @@ 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());
+  auto Symbolizer = std::move(SOFOr.get());
 
   // Process the raw profile.
   if (Error E = readRawProfile(std::move(DataBuffer)))
@@ -353,7 +353,11 @@ Error RawMemProfReader::initialize(std::unique_ptr<MemoryBuffer> DataBuffer) {
   if (Error E = setupForSymbolization())
     return E;
 
-  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