From: Ian Rogers <irogers@google.com>
To: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>,
Arnaldo Carvalho de Melo <acme@kernel.org>,
Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>,
Adrian Hunter <adrian.hunter@intel.com>,
James Clark <james.clark@linaro.org>,
Kan Liang <kan.liang@linux.intel.com>,
linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org,
Ian Rogers <irogers@google.com>
Subject: [PATCH 00/10] perf jevents: Block-indexed string compression and default JEVENTS_ARCH=all
Date: Fri, 13 Nov 2026 13:08:12 -0800 [thread overview]
Message-ID: <20261113210822.3112700-1-irogers@google.com> (raw)
Compiled-in PMU event and metric tables (pmu-events-in.o) currently
store ~6.9 MiB of uncompressed string data in .rodata on x86 alone,
causing JEVENTS_ARCH to default to $(SRCARCH) rather than all and
preventing out-of-the-box cross-architecture perf.data event/metric
resolution unless explicitly built with JEVENTS_ARCH=all.
Compressing big_c_string as a single whole-table stream would force perf
to allocate and decompress megabytes of unused CPU models' strings on
startup just to resolve a single event, whereas compressing individual
short strings suffers from poor compression ratios and per-string
framing overhead.
Instead, this series introduces "block-indexed string compression":
sorted, suffix-folded event and metric byte records are packed into
~8 KiB blocks without splitting records across block boundaries, each
block is compressed independently (sharing a single preset or trained
dictionary across blocks so ~8 KiB blocks retain high compression
ratios), and every uint32_t string offset is encoded as
(block_id << 16) | sub_offset. An ~8 KiB target block size sits at the
knee of the compression vs. random-access curve (smaller 1-4 KiB blocks
pay 22-128% more .rodata for per-block entropy headers and index
entries, while larger 16-64 KiB blocks yield <15% extra savings at 2-8x
higher decompression and page-fault cost per binary-search probe). At
runtime, pmu_events__get_string() uses a lock-free atomic block pointer
cache to decompress only the touched ~8 KiB blocks on demand, leaving
untouched CPU models' and non-host architectures' blocks compressed in
.rodata at zero runtime CPU or heap cost.
The series starts with a standalone BigCString raw-byte fix for
describe_metricgroup() binary-search ordering, prepares the string and
PMU table layout, adds the zlib, lzma, and zstd block compression
backends, and switches the default JEVENTS_ARCH to all:
- Bug fix, string layout, and hot-path isolation (Patches 1-4):
- Patch 1 stores raw NUL-delimited UTF-8 bytes in BigCString instead
of C-escaped strings, fixing suffix folding and describe_metricgroup()
binary-search ordering on prefix-overlapping names (such as "Bad" vs
"BadSpec"; Fixes: 66c6e0c10027) without changing empty-pmu-events.c
so it can be cherry-picked standalone.
- Patch 2 partitions non-folded BigCString event strings before metric
strings and sorts entries lexicographically by their raw UTF-8 byte
sequence within each partition so identically prefixed event names,
encodings, descriptions, and metric expressions cluster into
adjacent ~8 KiB blocks, improving block compression ratios by
~20-23%.
- Patch 3 stores PMU names directly as const char *pmu_name string
literals in struct pmu_table_entry (only 68 unique PMU names / 536 B
across ~443 rows across all architectures, already in .data.rel.ro)
so the compiler/linker merge them in .rodata.str1.1 and hot PMU
wildcard scans never touch big_c_string or trigger block
decompression.
- Patch 4 encapsulates big_c_string offset lookups behind
pmu_events__get_string(uint32_t offset) across pmu-events.c and
pmu-events-string.c.
- On-demand block decompression backends (Patches 5-8):
- Patch 5 packs big_c_string into ~8 KiB record-aligned blocks indexed
by (block_id << 16) | sub_offset, adds lock-free thread-safe atomic
per-block decompression on demand, and adds --compress=zlib using
raw Deflate with a <= 32 KiB preset dictionary.
- Patch 6 adds --compress=lzma using raw LZMA2 per block with a 64 KiB
dictionary window.
- Patch 7 adds --compress=zstd using ZSTD_decompress_usingDDict() per
block with a once-digested shared 64 KiB ZSTD_DDict (~26% smaller
.rodata than dictionary-free ~8 KiB zstd blocks).
- Patch 8 wires JEVENTS_COMPRESS into Makefile.perf and
pmu-events/Build, preferring zstd, then zlib, then lzma, and falling
back to none.
- Testing and JEVENTS_ARCH=all default (Patches 9-10):
- Patch 9 adds prefix-overlapping metricgroups.json test coverage and
an 8-thread concurrent event/metric/metricgroup stress test in
perf test pmu-events.
- Patch 10 switches the default JEVENTS_ARCH to all. Bundling all
architectures (x86, arm64, powerpc, riscv, s390, nds32) with zstd
shrinks pmu-events-in.o from 7.16 MiB (x86 + none) to 1.11 MiB
(all + zstd, -84.5%) and cuts the stripped perf binary from
13.32 MiB to 7.28 MiB (-45.4%), with ~3 ms median wall-clock
overhead on 'perf stat true'.
AI Assistance Disclosure (per Documentation/process/coding-assistants.rst
and Documentation/process/generated-content.rst):
- Tools used: Antigravity coding assistant and Sashiko automated patch
review.
- Summary of prompts and assistance: Interactive design and
implementation of the BigCString raw-byte fix and alphabetical
sorting, struct pmu_table_entry PMU name string literals, lock-free
8 KiB block-indexed decompression across zlib, lzma, and zstd,
Makefile.config/Build integration, multithreaded unit tests,
size/latency benchmarking, and Sashiko review fixes.
- Testing performed: Built and tested JEVENTS_COMPRESS={none,zlib,lzma,zstd}
and NO_JEVENTS=1, JEVENTS_ARCH={x86,all}, AddressSanitizer +
LeakSanitizer, perf test (pmu-events, make, metric parsing), and
scripts/checkpatch.pl.
Ian Rogers (10):
perf jevents: Store raw bytes in BigCString instead of C-escaped
strings
perf jevents: Sort BigCString entries alphabetically
perf jevents: Store PMU names as string literals in struct
pmu_table_entry
perf jevents: Encapsulate big_c_string lookups behind
pmu_events__get_string()
perf jevents: Add block-indexed string packing and --compress=zlib
perf jevents: Add --compress=lzma block compression backend
perf jevents: Add --compress=zstd block compression backend
perf build: Enable jevents string compression when available
perf tests pmu-events: Test metricgroup descriptions and concurrent
lookups
perf build: Default JEVENTS_ARCH to all
tools/perf/.gitignore | 1 +
tools/perf/Makefile.config | 9 +-
tools/perf/Makefile.perf | 13 +-
tools/perf/pmu-events/Build | 49 +-
.../arch/test/test_soc/cpu/metricgroups.json | 4 +
tools/perf/pmu-events/empty-pmu-events.c | 7804 +++++++++--------
tools/perf/pmu-events/jevents.py | 967 +-
tools/perf/tests/make | 5 +-
tools/perf/tests/pmu-events.c | 209 +-
9 files changed, 5015 insertions(+), 4046 deletions(-)
create mode 100644 tools/perf/pmu-events/arch/test/test_soc/cpu/metricgroups.json
base-commit: 4af65363b11fc4fe65fcb497f68bbe4f3e3a4d2c
--
2.56.1.703.gf848ed807c-goog
next reply other threads:[~2026-11-13 21:08 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-13 21:08 Ian Rogers [this message]
2026-11-13 21:08 ` [PATCH 01/10] perf jevents: Store raw bytes in BigCString instead of C-escaped strings Ian Rogers
2026-11-13 21:21 ` sashiko-bot
2026-11-13 21:08 ` [PATCH 02/10] perf jevents: Sort BigCString entries alphabetically Ian Rogers
2026-11-13 21:12 ` sashiko-bot
2026-11-13 21:08 ` [PATCH 03/10] perf jevents: Store PMU names as string literals in struct pmu_table_entry Ian Rogers
2026-11-13 21:13 ` sashiko-bot
2026-11-13 21:08 ` [PATCH 04/10] perf jevents: Encapsulate big_c_string lookups behind pmu_events__get_string() Ian Rogers
2026-11-13 21:12 ` sashiko-bot
2026-11-13 21:08 ` [PATCH 05/10] perf jevents: Add block-indexed string packing and --compress=zlib Ian Rogers
2026-11-13 21:16 ` sashiko-bot
2026-11-13 21:08 ` [PATCH 06/10] perf jevents: Add --compress=lzma block compression backend Ian Rogers
2026-11-13 21:13 ` sashiko-bot
2026-11-13 21:08 ` [PATCH 07/10] perf jevents: Add --compress=zstd " Ian Rogers
2026-11-13 21:13 ` sashiko-bot
2026-11-13 21:08 ` [PATCH 08/10] perf build: Enable jevents string compression when available Ian Rogers
2026-11-13 21:17 ` sashiko-bot
2026-11-13 21:08 ` [PATCH 09/10] perf tests pmu-events: Test metricgroup descriptions and concurrent lookups Ian Rogers
2026-11-13 21:20 ` sashiko-bot
2026-11-13 21:08 ` [PATCH 10/10] perf build: Default JEVENTS_ARCH to all Ian Rogers
2026-11-13 21:21 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261113210822.3112700-1-irogers@google.com \
--to=irogers@google.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=james.clark@linaro.org \
--cc=jolsa@kernel.org \
--cc=kan.liang@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox