Skip to content

Commit 6a7bbf7

Browse files
[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.
1 parent 6ce23ea commit 6a7bbf7

File tree

2 files changed

+20
-16
lines changed

2 files changed

+20
-16
lines changed

llvm/include/llvm/ProfileData/RawMemProfReader.h

+5-6
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,14 @@ class RawMemProfReader final : public MemProfReader {
147147
llvm::SmallVectorImpl<SegmentEntry> &Seg,
148148
llvm::MapVector<uint64_t, MemInfoBlock> &Prof,
149149
CallStackMap &SM, bool KeepName = false)
150-
: Symbolizer(std::move(Sym)), SegmentInfo(Seg.begin(), Seg.end()),
151-
CallstackProfileData(Prof), StackMap(SM), KeepSymbolName(KeepName) {
150+
: SegmentInfo(Seg.begin(), Seg.end()), CallstackProfileData(Prof),
151+
StackMap(SM), KeepSymbolName(KeepName) {
152152
// We don't call initialize here since there is no raw profile to read. The
153153
// test should pass in the raw profile as structured data.
154154

155155
// If there is an error here then the mock symbolizer has not been
156156
// initialized properly.
157-
if (Error E = symbolizeAndFilterStackFrames())
157+
if (Error E = symbolizeAndFilterStackFrames(std::move(Sym)))
158158
report_fatal_error(std::move(E));
159159
if (Error E = mapRawProfileToRecords())
160160
report_fatal_error(std::move(E));
@@ -173,7 +173,8 @@ class RawMemProfReader final : public MemProfReader {
173173
// callstacks from the raw profile. Also prune callstack frames which we can't
174174
// symbolize or those that belong to the runtime. For profile entries where
175175
// the entire callstack is pruned, we drop the entry from the profile.
176-
Error symbolizeAndFilterStackFrames();
176+
Error symbolizeAndFilterStackFrames(
177+
std::unique_ptr<llvm::symbolize::SymbolizableModule> Symbolizer);
177178
// Construct memprof records for each function and store it in the
178179
// `FunctionProfileData` map. A function may have allocation profile data or
179180
// callsite data or both.
@@ -183,8 +184,6 @@ class RawMemProfReader final : public MemProfReader {
183184

184185
// The profiled binary.
185186
object::OwningBinary<object::Binary> Binary;
186-
// A symbolizer to translate virtual addresses to code locations.
187-
std::unique_ptr<llvm::symbolize::SymbolizableModule> Symbolizer;
188187
// The preferred load address of the executable segment.
189188
uint64_t PreferredTextSegmentAddress = 0;
190189
// The base address of the text segment in the process during profiling.

llvm/lib/ProfileData/RawMemProfReader.cpp

+15-10
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,13 @@ Error RawMemProfReader::initialize(std::unique_ptr<MemoryBuffer> DataBuffer) {
336336
inconvertibleErrorCode()),
337337
FileName);
338338

339+
// Process the raw profile.
340+
if (Error E = readRawProfile(std::move(DataBuffer)))
341+
return E;
342+
343+
if (Error E = setupForSymbolization())
344+
return E;
345+
339346
auto *Object = cast<object::ObjectFile>(Binary.getBinary());
340347
std::unique_ptr<DIContext> Context = DWARFContext::create(
341348
*Object, DWARFContext::ProcessDebugRelocations::Process);
@@ -344,16 +351,13 @@ Error RawMemProfReader::initialize(std::unique_ptr<MemoryBuffer> DataBuffer) {
344351
Object, std::move(Context), /*UntagAddresses=*/false);
345352
if (!SOFOr)
346353
return report(SOFOr.takeError(), FileName);
347-
Symbolizer = std::move(SOFOr.get());
348-
349-
// Process the raw profile.
350-
if (Error E = readRawProfile(std::move(DataBuffer)))
351-
return E;
352-
353-
if (Error E = setupForSymbolization())
354-
return E;
354+
auto Symbolizer = std::move(SOFOr.get());
355355

356-
if (Error E = symbolizeAndFilterStackFrames())
356+
// The symbolizer ownership is moved into symbolizeAndFilterStackFrames so
357+
// that it is freed automatically at the end, when it is no longer used. This
358+
// reduces peak memory since it won't be live while also mapping the raw
359+
// profile into records afterwards.
360+
if (Error E = symbolizeAndFilterStackFrames(std::move(Symbolizer)))
357361
return E;
358362

359363
return mapRawProfileToRecords();
@@ -469,7 +473,8 @@ Error RawMemProfReader::mapRawProfileToRecords() {
469473
return Error::success();
470474
}
471475

472-
Error RawMemProfReader::symbolizeAndFilterStackFrames() {
476+
Error RawMemProfReader::symbolizeAndFilterStackFrames(
477+
std::unique_ptr<llvm::symbolize::SymbolizableModule> Symbolizer) {
473478
// The specifier to use when symbolization is requested.
474479
const DILineInfoSpecifier Specifier(
475480
DILineInfoSpecifier::FileLineInfoKind::RawValue,

0 commit comments

Comments
 (0)