Re: [PATCH v7 3/4] perf script: Add --lazy-load-symbols to load symbol names lazily
From: Namhyung Kim
Date: Sat Nov 14 2026 - 22:51:15 EST
On Fri, Nov 13, 2026 at 09:09:08PM -0800, Alireza Haghdoost wrote:
> This patch adds a --lazy-load-symbols option to perf script. With it,
> perf reads the name of a userspace ELF symbol only when a lookup returns
> that symbol. Eager loading stays the default.
>
> perf script loads the whole ELF symbol table of every DSO that appears
> in a sample and keeps every symbol, with its demangled name, until exit.
> Most of those symbols are never sampled, and their names take most of
> the memory. On a large profile this is the main memory cost of perf
> script, and in a memory-limited cgroup it gets perf OOM-killed.
>
> The loader still creates every symbol, so end fixup, duplicate
> selection, PLT synthesis and IFUNC marking do not change. It stores the
> file offset of each name instead of the name, in a union with the name
> pointer, and SYMBOL_FLAG_LAZY_NAME tells which one is set. Lookups load
> the name of the symbol they return, and code that walks all symbols of
> a DSO gets them from dso__named_symbols(), which loads every name. Names
> are read under the DSO lock with pread() from the symbol table file,
> which is open only while perf reads them. A name that cannot be read
> becomes "[unknown]", and address lookups do not return that symbol.
>
> A few names are still read at load time: aliases that duplicate
> selection can tell apart only by name, and IFUNC symbols, whose names
> PLT synthesis uses. A .dynsym entry that copies a lazy .symtab symbol is
> skipped, since duplicate selection would drop it anyway after reading
> both names.
>
> The offsets are only valid in the file that perf loaded. perf records
> its device, inode, size and mtime, and checks them each time it opens
> the file again. If the binary was replaced in the meantime, for example
> by a deploy, or the path now resolves to another file because a mount
> namespace went away, perf warns once and shows the remaining lazy
> symbols of that DSO as "[unknown]" rather than print wrong names.
Please separate this part into another patch. That would make my life a
bit easier. :) As I said, you can use dso_id instead.
>
> The kernel, modules, PPC64 .opd and .gnu_debugdata still load names
> eagerly.
>
> On a 45,073-sample callchain profile of a large C++ service (about 1M
> symbols), lazy loading cuts max RSS from 327 MiB to 135 MiB and run
> time from 2.9 to 1.3 seconds, with identical output.
Nice!
Thanks,
Namhyung