From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E56A64C680A; Tue, 15 Sep 2026 18:43:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789497808; cv=none; b=NN8tqWJswomYnVMeM3fMXHVTUqQ5C3MXZ4bVKCiAXyaTUQGE2WjOllhP3OgyDeOo3CPkD9mIowx+GTawnXXLa4MOURminR36pFL/iz67N7qQ5PaqEMeVcNN5zYGepeCEzW4VNyrs0IpgS1cMHaclz2RCorInoqwXiSu3INAkiIA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789497808; c=relaxed/simple; bh=BikG+MUQZlklxvTmT8pKAp/VLf/cXClH7BY/kzM+Cg8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CziQH6von/qr0fgGaSAJRjEODdOtQEsDz1eTrn8PM+cxYNC9Cvl7hcMsVoOI7lO+KJ+J1Ptlr8m19ZKuOMUp8q0+sbGoEgrBdGZDtNCnulUxn+eCDslsQ2EB+EdUZxthDM4E4BxWK0ehT2T6dSA0JI+427XDS4PxT4XFDDF/2Sg= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=q/lkv6C8; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="q/lkv6C8" Received: by smtp.kernel.org (Postfix) with ESMTPS id 8646EC2BD00; Tue, 15 Sep 2026 18:43:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1789497807; bh=BikG+MUQZlklxvTmT8pKAp/VLf/cXClH7BY/kzM+Cg8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=q/lkv6C8UeQV6S/Jv5KtJRj/z1UldAEhqnAvI+eWdxXtUb6F500jkcFVDbWEzXStY 5yRb6XJ2xKpdMUEpjwXUYHj2/qoddaMYurbog5tu6M39P7uMjv2OoVX+3kmPlnWHSe VvIegvP5RHv+ZjGzwg7dbZQLLQ3jtik0OKnvCp3B0SoC8FsOC+ZbH9ZmViMeXdVsTK q9ibkOTTh22H+v+9XV8qZz3AEiNj0h4Q/W775UwVFDv0KH/dprcLVaaqX8/hF59ZBc je6K7qGSl8S8BoxYz2PwHg7GptCrUBBlbQi3JtN159ZDNx5IcSOkaxv022Ewjj0bRG 3QqdDROQOVoEw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6DB8AC982C1; Tue, 15 Sep 2026 18:43:27 +0000 (UTC) From: Alireza Haghdoost via B4 Relay Date: Tue, 15 Sep 2026 11:42:46 -0700 Subject: [PATCH 4/4] perf script: Document and test --lazy-load-symbols and --max-symbol-bytes Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20260915-perf-symbol-memory-send-v1-4-1d3360e21f07@uber.com> References: <20260915-perf-symbol-memory-send-v1-0-1d3360e21f07@uber.com> In-Reply-To: <20260915-perf-symbol-memory-send-v1-0-1d3360e21f07@uber.com> To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , James Clark , Andrii Nakryiko , Alexei Starovoitov Cc: linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, Alireza Haghdoost X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=6198; i=haghdoost@uber.com; h=from:subject:message-id; bh=ozeisEeLUlyeoorFaW7r4WB+nw0aEmnGGVlEP7mmb2o=; b=owEBiQJ2/ZANAwAIAVNlBDxl2ALYAcsmYgBqqZHOO79qSbapVu7FstSxOFn6KxUcXOhoUCYQ1 bXfEiLi0MCJAk8EAAEIADkWIQS5+sFL3gX/8PrA0S1TZQQ8ZdgC2AUCaqmRzhsUgAAAAAAEAA5t YW51MiwyLjUrMS4xMiwwLDMACgkQU2UEPGXYAth0mA/+Pt0cuUTq8AeRJ2ktRGG2FnZOgPD/HtS JOqLpmcMT5dRHYsgVYt0K6XyaVNBLT1KXAaQ3UIYyWv7ikqiyd2cTFrWXlVPij2wT6ItcL5blXF pAMifxDaeljgtOE0oqwG2+Q7IO0qvF+qtXZEmlqc2qn8DLyVrjX1JXIZXgw+6OLBYWv+iraL71H 62u7atJSwkfimQlKv6yO/5xrsFrx06Tq9/lGs/KBaB/R48/lK+F9/qgp2OvwoDvOY4B/+FTbTBW hdwzzPKgCUbWrDXmwjtkWiMHlnUG9L5hXTFZeWhKU6KeSyuIoSq0R6VUXYhNrjbS+lL+8FpbnPv +pz2zEL6mq1kt4u4IHpGFiBM+azREB4ma+riwivc6rkYHfkqNeGigunSIXoahnT5pViKEtUY7+g Re7/cvBUq8uyrtsi9VGO7N1JWAbaLEgRyfZAHSir0VPw/r14h5KIUaCXP4UYEkCKxJQJvdrlTdE t7bQPszpi0I20M7MkTBd7TQOFTXWDXc3Og8UTHLqquoZZz9Iio3loEmGddBg0sDNSEyR2DNo5lu KSoiqAqTkweB9lvanN5zphq7ThJUOqHpopk3vJK01Zm+yHtJDcH8yp0InOQoORgx0rCPd+dF5Wt vrUgMgj0wQcwfmywJr4bUFfExIDOqqe3HHLAr4GNur2OSfMgWKRU= X-Developer-Key: i=haghdoost@uber.com; a=openpgp; fpr=B9FAC14BDE05FFF0FAC0D12D5365043C65D802D8 X-Endpoint-Received: by B4 Relay for haghdoost@uber.com/default with auth_id=764 X-Original-From: Alireza Haghdoost Reply-To: haghdoost@uber.com From: Alireza Haghdoost Document both new options in perf-script.txt: their interaction, the memory tradeoff, that lazy loading applies only to userspace ELF DSOs (kernel DSOs and modules always load eagerly), and that output may differ from the default loader for some targets. Add a shell test that records a small profile with callchains and asserts: - --lazy-load-symbols produces output byte-identical to the eager loader, and that at least one symbol actually resolved (so the comparison can't pass vacuously on all-[unknown] output); - --max-symbol-bytes=1K, with and without lazy loading, forces [unknown] resolution with a single warning and exit code 0 (no crash). Signed-off-by: Alireza Haghdoost Assisted-by: Kimi:K3 --- tools/perf/Documentation/perf-script.txt | 24 +++++ tools/perf/tests/shell/script_lazy_load_symbols.sh | 120 +++++++++++++++++++++ 2 files changed, 144 insertions(+) diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index 200ea25891d8..b5a90ff22342 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt @@ -412,6 +412,30 @@ include::itrace.txt[] Default: 127 +--lazy-load-symbols:: + Resolve symbols lazily instead of eagerly loading the full + symbol table of every DSO that appears in a sample. A compact + sorted index is built per DSO and only the addresses that appear + in samples are materialized into symbols, with names read from the + file's string table at lookup time. This sharply reduces memory + (and usually time) for profiles of large binaries where only a + small fraction of the symbol table is referenced. This applies only + to userspace ELF DSOs; kernel DSOs and modules always load eagerly. + Output may differ from the default loader for some targets + (e.g. PPC64 .opd, .gnu_debugdata, or split debuginfo). Default: off. + +--max-symbol-bytes:: + Limit the bytes held in struct symbol allocations (and, with + --lazy-load-symbols, the lazy index) for DSOs on the ELF symbol + loader path -- userspace DSOs plus vmlinux-as-ELF and kernel + modules. This is not a cap on all symbol memory or RSS: symbols + from kallsyms, JIT maps, PLT synthesis, and libbfd are counted + but not capped. Accepts a size with a B/K/M/G suffix (e.g. 128M). + When the budget is exceeded, further symbols resolve to [unknown] + and a warning is printed. This is a safety net independent of + --lazy-load-symbols and can be used with or without it. Default: 0 + (unlimited). + --ns:: Use 9 decimal places when displaying time (i.e. show the nanoseconds) diff --git a/tools/perf/tests/shell/script_lazy_load_symbols.sh b/tools/perf/tests/shell/script_lazy_load_symbols.sh new file mode 100755 index 000000000000..799c61e2f3e8 --- /dev/null +++ b/tools/perf/tests/shell/script_lazy_load_symbols.sh @@ -0,0 +1,120 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# perf script lazy symbol loading tests +# +# Verifies that --lazy-load-symbols produces output identical to the default +# eager symbol loader, and that --max-symbol-bytes caps symbol allocations +# (emitting [unknown] plus a warning) without crashing. + +set -e + +shelldir=$(dirname "$0") +# shellcheck source=lib/perf_has_symbol.sh +. "${shelldir}"/lib/perf_has_symbol.sh + +testsym="test_loop" + +skip_test_missing_symbol ${testsym} + +err=0 +temp_dir=$(mktemp -d /tmp/__perf_test.lazy_load.XXXXX) +perfdata="${temp_dir}/perf.data" +eager_out="${temp_dir}/eager.out" +lazy_out="${temp_dir}/lazy.out" + +cleanup() { + rm -rf "${temp_dir}" + trap - EXIT TERM INT +} + +trap_cleanup() { + echo "Unexpected signal in ${FUNCNAME[1]}" + cleanup + exit 1 +} +trap trap_cleanup EXIT TERM INT + +test_lazy_load_identical() { + echo "Lazy-load output matches eager loader" + + # Record a small profile with callchains so symbol resolution runs. + if ! perf record -o "${perfdata}" -g -- perf test -w thloop 2> /dev/null + then + echo "Lazy-load identical [Skipped record not supported]" + return + fi + + if ! perf script -i "${perfdata}" 2> /dev/null > "${eager_out}" || \ + ! perf script --lazy-load-symbols -i "${perfdata}" 2> /dev/null > "${lazy_out}" + then + echo "Lazy-load identical [Failed perf script error]" + err=1 + return + fi + + # The comparison is only meaningful if something actually resolved; + # two all-[unknown] outputs would also match. + if ! grep -q "${testsym}" "${eager_out}" + then + echo "Lazy-load identical [Skipped no ${testsym} resolved]" + return + fi + + if ! cmp -s "${eager_out}" "${lazy_out}" + then + echo "Lazy-load identical [Failed output differs]" + err=1 + return + fi + echo "Lazy-load identical [Success]" +} + +test_max_symbol_bytes() { + echo "--max-symbol-bytes budget enforcement" + + # Depends on ${perfdata} from test_lazy_load_identical. + if [ ! -s "${perfdata}" ] + then + echo "--max-symbol-bytes budget [Skipped record not supported]" + return + fi + + # A tiny budget forces most symbols to be dropped as [unknown], + # with a single warning, and must not crash. + if ! perf script --max-symbol-bytes=1K -i "${perfdata}" > /dev/null \ + 2> "${temp_dir}/budget.err" + then + echo "--max-symbol-bytes budget [Failed nonzero exit]" + err=1 + return + fi + if ! grep -q "symbol memory budget exceeded" "${temp_dir}/budget.err" + then + echo "--max-symbol-bytes budget [Failed missing warning]" + err=1 + return + fi + + if ! perf script --lazy-load-symbols --max-symbol-bytes=1K \ + -i "${perfdata}" > /dev/null 2> "${temp_dir}/lazy-budget.err" + then + echo "--max-symbol-bytes lazy budget [Failed nonzero exit]" + err=1 + return + fi + warnings=$(grep -c "symbol memory budget exceeded" \ + "${temp_dir}/lazy-budget.err" || true) + if [ "${warnings}" -ne 1 ] + then + echo "--max-symbol-bytes lazy budget [Failed warning count: ${warnings}]" + err=1 + return + fi + echo "--max-symbol-bytes budget [Success]" +} + +test_lazy_load_identical +test_max_symbol_bytes + +cleanup +exit $err -- Git-155)