From d6f82852479c9962239a634688e60a3d1e873ffb Mon Sep 17 00:00:00 2001 From: Arni Dagur Date: Tue, 30 Jun 2026 22:42:14 +0100 Subject: [PATCH] Add `profiling_frameptr` feature for jemalloc `--enable-prof-frameptr` Similar to https://github.com/tikv/jemallocator/pull/159, we introduce `profiling_frameptr` to enable frame-pointer based profiling via `--enable-prof-frameptr`. This option was introduced in https://github.com/jemalloc/jemalloc/pull/2712, which was released as a part of `5.3.1`. We make `profiling_frameptr` mutually exclusive with `profiling_libunwind`, since jemalloc configures just a single backtrace method, and we don't want it to silently prefer one over the other. Signed-off-by: Arni Dagur --- jemalloc-ctl/Cargo.toml | 2 ++ jemalloc-sys/Cargo.toml | 2 ++ jemalloc-sys/README.md | 11 ++++++++++- jemalloc-sys/build.rs | 22 +++++++++++++++++++++- jemallocator/Cargo.toml | 2 ++ 5 files changed, 37 insertions(+), 2 deletions(-) diff --git a/jemalloc-ctl/Cargo.toml b/jemalloc-ctl/Cargo.toml index 1f93c84a4..588a44668 100644 --- a/jemalloc-ctl/Cargo.toml +++ b/jemalloc-ctl/Cargo.toml @@ -37,7 +37,9 @@ tikv-jemallocator = { path = "../jemallocator", version = "0.7.0" } default = [] stats = ["tikv-jemalloc-sys/stats"] profiling = ["tikv-jemalloc-sys/profiling"] +# `profiling_libunwind` and `profiling_frameptr` are mutually exclusive profiling_libunwind = ["tikv-jemalloc-sys/profiling_libunwind", "profiling"] +profiling_frameptr = ["tikv-jemalloc-sys/profiling_frameptr", "profiling"] use_std = [ "libc/use_std" ] disable_initial_exec_tls = ["tikv-jemalloc-sys/disable_initial_exec_tls"] diff --git a/jemalloc-sys/Cargo.toml b/jemalloc-sys/Cargo.toml index 9b3d922f1..3547713b4 100644 --- a/jemalloc-sys/Cargo.toml +++ b/jemalloc-sys/Cargo.toml @@ -41,7 +41,9 @@ cc = "^1.0.13" [features] default = ["background_threads_runtime_support"] profiling = [] +# `profiling_libunwind` and `profiling_frameptr` are mutually exclusive profiling_libunwind = ["profiling"] +profiling_frameptr = ["profiling"] debug = [] background_threads_runtime_support = [] background_threads = [ "background_threads_runtime_support" ] diff --git a/jemalloc-sys/README.md b/jemalloc-sys/README.md index bce9ae000..f727b36ff 100644 --- a/jemalloc-sys/README.md +++ b/jemalloc-sys/README.md @@ -42,6 +42,7 @@ This crate provides following cargo feature flags: list that appears to function correctly: * `libunwind` (requires --enable-prof-libunwind) + * frame-pointer walk (requires --enable-prof-frameptr; Linux only) * `libgcc` (unless --disable-prof-libgcc) * `gcc intrinsics` (unless --disable-prof-gcc) @@ -52,7 +53,15 @@ This crate provides following cargo feature flags: multi-threaded programs using `_Unwind_Backtrace`. Enables `profiling` automatically. On Linux, this requires `libunwind-dev` (or `libunwind-devel`) to be installed. On macOS/iOS, unwind symbols are provided by the system and - no extra library is needed. + no extra library is needed. Mutually exclusive with `profiling_frameptr`. + +* `profiling_frameptr` (configure `jemalloc` with `--enable-prof-frameptr`): + Force jemalloc to use its Linux frame-pointer unwinder for backtracing during + heap profiling instead of libgcc/gcc-intrinsics DWARF unwind. Enables + `profiling` automatically. Only supported on Linux targets. Profiled code + should be built with frame pointers (for example Rust + `-C force-frame-pointers=yes`, C/C++ `-fno-omit-frame-pointer`) for useful + stacks. Mutually exclusive with `profiling_libunwind`. * `stats` (configure `jemalloc` with `--enable-stats`): Enable statistics gathering functionality. See the `jemalloc`'s "`opt.stats_print`" option diff --git a/jemalloc-sys/build.rs b/jemalloc-sys/build.rs index 845b9d43f..4a4671db0 100644 --- a/jemalloc-sys/build.rs +++ b/jemalloc-sys/build.rs @@ -295,7 +295,19 @@ fn main() { cmd.arg("--enable-prof"); } - if env::var("CARGO_FEATURE_PROFILING_LIBUNWIND").is_ok() { + let profiling_libunwind = env::var("CARGO_FEATURE_PROFILING_LIBUNWIND").is_ok(); + let profiling_frameptr = env::var("CARGO_FEATURE_PROFILING_FRAMEPTR").is_ok(); + // jemalloc picks a single backtrace method at configure time, and libunwind + // wins over frameptr if both are enabled. We make them mutually exclusive to + // avoid confusion resulting from configuration priority. + if profiling_libunwind && profiling_frameptr { + panic!( + "features `profiling_libunwind` and `profiling_frameptr` are mutually \ + exclusive; enable only one heap-profiling backtrace method" + ); + } + + if profiling_libunwind { info!("CARGO_FEATURE_PROFILING_LIBUNWIND set"); cmd.arg("--enable-prof-libunwind"); // On Apple platforms unwind symbols live in libSystem, and on @@ -306,6 +318,14 @@ fn main() { } } + if profiling_frameptr { + if !target.contains("linux") { + panic!("feature `profiling_frameptr` is only supported on Linux targets"); + } + info!("CARGO_FEATURE_PROFILING_FRAMEPTR set"); + cmd.arg("--enable-prof-frameptr"); + } + if env::var("CARGO_FEATURE_STATS").is_ok() { info!("CARGO_FEATURE_STATS set"); cmd.arg("--enable-stats"); diff --git a/jemallocator/Cargo.toml b/jemallocator/Cargo.toml index 6d9a466d8..1a986a2e8 100644 --- a/jemallocator/Cargo.toml +++ b/jemallocator/Cargo.toml @@ -48,7 +48,9 @@ tikv-jemalloc-ctl = { path = "../jemalloc-ctl", version = "0.7.0" } default = ["background_threads_runtime_support"] alloc_trait = [] profiling = ["tikv-jemalloc-sys/profiling"] +# `profiling_libunwind` and `profiling_frameptr` are mutually exclusive profiling_libunwind = ["tikv-jemalloc-sys/profiling_libunwind", "profiling"] +profiling_frameptr = ["tikv-jemalloc-sys/profiling_frameptr", "profiling"] debug = ["tikv-jemalloc-sys/debug"] stats = ["tikv-jemalloc-sys/stats"] background_threads_runtime_support = ["tikv-jemalloc-sys/background_threads_runtime_support"]