Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Changelog

## v0.3.23

### New Features (experimental)

- **`--java-engine async-profiler` (experimental, opt-in)** — instead of reconstructing Java stacks from eBPF (which needs `-XX:+PreserveFramePointer` for JIT frames), profile-bee can delegate to [async-profiler](https://github.com/async-profiler/async-profiler), whose in-process `AsyncGetCallTrace` walks Java stacks without frame pointers and names JIT/interpreter/inlined frames. profile-bee attaches `asprof` for the profiling window; its `-o collapsed` output is the same folded format profile-bee emits, so merging is a splice.
- **Single `--pid`**: eBPF is already scoped to that process, so its collapse is replaced wholesale by async-profiler's output.
- **System-wide** (no `--pid`): every discovered JVM is attached; each attached JVM's eBPF stacks are dropped (matched by the `(pid)` in the auto-enabled `--group-by-process` root) and replaced with async-profiler's, while native processes — and any JVM that refused attach or produced no samples — keep their eBPF stacks. profile-bee's own JVM auto-discovery is disabled in this mode so both don't attach the same JVMs.
- **No manual install:** `asprof` is used from `$ASPROF`/`$PATH`/common install roots if present, otherwise the pinned official release for the host arch (x86_64/aarch64) is **downloaded, SHA-256-verified, and cached** on first use. The cache is a world-readable dir (`/var/tmp/profile-bee`, override `$PROFILE_BEE_CACHE`) so a target JVM of any uid can `dlopen` `libasyncProfiler.so` when profile-bee runs as root. Nothing unverified is executed; offline hosts can still pre-place the binary or set `$ASPROF`.
- Requires `--time`; batch (`--collapse`/`--svg`/`--json`) output only (streaming/serve/TUI is a follow-up). Falls back to eBPF stacks (with a logged reason) when prerequisites are unmet, per-JVM.

### Validated

- aarch64 fleet host (Corretto 17, G1GC, no `-XX:+PreserveFramePointer`): the stress JVM resolved 28,887 frames with ~0.01% unknown (vs ~22% eBPF-only), naming the real Netty/Membrain client call graph, while non-JVM processes kept eBPF stacks.

## v0.3.22

### New Features
Expand Down
43 changes: 38 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ Run `probee` with no arguments or `probee --help` for the full list of options a
- **Automatic termination** — stops when `-p` target or child process exits
- **Rust & C++ demangling** — via gimli/blazesym
- **Java / HotSpot profiling** — auto-detects JVMs and resolves JIT-compiled methods from `/tmp/perf-<pid>.map`, auto-dumping it via `Compiler.perfmap` (JDK 17+) / HotSpot attach with no manual `jcmd`. Injects `-XX:+PreserveFramePointer` when launching `java`, scopes attach/dump to the profiled target (never touches other JVMs), and works in CLI, TUI, and `--serve` (see [docs/java_profiling.md](docs/java_profiling.md))
- **async-profiler engine (experimental)** — `--java-engine async-profiler` delegates Java stacks to [async-profiler](https://github.com/async-profiler/async-profiler) (AsyncGetCallTrace), so JIT/interpreter/inlined frames resolve **without `-XX:+PreserveFramePointer`**. Works per-`--pid` or system-wide (attaches every discovered JVM, eBPF for the rest). `asprof` is used from `$ASPROF`, `$PATH`, `/opt/async-profiler`, `/usr/local/async-profiler`, or the cache if present; only when none is found is the pinned release auto-downloaded (SHA-256-verified) into a world-readable cache. Batch output only; see below
- **Category-based coloring** — frames are colored by category (kernel, kernel I/O, JavaScript/V8, Java/JVM, native, synthetic) consistently across the TUI, SVG, and HTML/serve renderers
- **BPF-based aggregation** — stack counting in kernel to reduce userspace data transfer
- **Group by CPU / process** — per-core or per-PID flamegraph breakdown (`--group-by-cpu`, `--group-by-process`)
Expand Down Expand Up @@ -455,7 +456,7 @@ let session = ProfilingSession::new(config).await?;

- Linux only (requires eBPF support)
- Architecture: x86_64 and aarch64 supported (frame-pointer + DWARF unwinding, Java/HotSpot `Method*` naming)
- JIT-compiled code (HotSpot Java, V8/Node) is symbolized via `/tmp/perf-<pid>.map`; interpreter and inlined frames are not yet reconstructed. `Compiler.perfmap` auto-dump requires JDK 17+ (on JDK 8/11 use perf-map-agent/async-profiler)
- JIT-compiled code (HotSpot Java, V8/Node) is symbolized via `/tmp/perf-<pid>.map`; interpreter and inlined frames are not yet reconstructed by the eBPF engine. `Compiler.perfmap` auto-dump requires JDK 17+ (on JDK 8/11 use perf-map-agent/async-profiler). For full Java fidelity without `-XX:+PreserveFramePointer`, use `--java-engine async-profiler` (batch output only)
- [VDSO](https://man7.org/linux/man-pages/man7/vdso.7.html) `.eh_frame` parsed for DWARF unwinding; VDSO symbolization not yet supported

## Development
Expand Down
2 changes: 1 addition & 1 deletion profile-bee-common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "profile-bee-common"
version = "0.3.22"
version = "0.3.23"
edition = "2021"
license = "MIT"
description = "Shared types between profile-bee userspace and eBPF programs"
Expand Down
2 changes: 1 addition & 1 deletion profile-bee-symbols/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "profile-bee-symbols"
version = "0.3.22"
version = "0.3.23"
edition = "2021"
license = "MIT"
description = "Shared symbol extraction and FileId computation for profile-bee ecosystem"
Expand Down
4 changes: 2 additions & 2 deletions profile-bee-tui/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "profile-bee-tui"
version = "0.3.22"
version = "0.3.23"
edition = "2021"
license = "MIT"
description = "Terminal-based flamegraph viewer for profile-bee (forked from flamelens)"
Expand All @@ -13,7 +13,7 @@ repository = "https://github.com/zz85/profile-bee"
[dependencies]
anyhow = "1.0"
crossterm = { version = "0.28.1", features = ["use-dev-tty"] }
profile-bee-common = { version = "0.3.22", path = "../profile-bee-common", features = ["color"] }
profile-bee-common = { version = "0.3.23", path = "../profile-bee-common", features = ["color"] }
ratatui = { version = "0.29.0", features = ["unstable-rendered-line-info"] }
regex = "1.10"
serde = { version = "1.0", features = ["derive"] }
Expand Down
10 changes: 6 additions & 4 deletions profile-bee/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "profile-bee"
version = "0.3.22"
version = "0.3.23"
edition = "2021"
license = "MIT"
description = "eBPF-based CPU profiler with flamegraph generation, DWARF unwinding, and interactive TUI"
Expand All @@ -22,9 +22,9 @@ include = [
[dependencies]
aya = { package = "profile-bee-aya", version = "0.13.2" }
aya-log = { package = "profile-bee-aya-log", version = "0.2.2" }
profile-bee-common = { version = "0.3.22", path = "../profile-bee-common", features=["user", "color"] }
profile-bee-symbols = { version = "0.3.22", path = "../profile-bee-symbols" }
profile-bee-tui = { version = "0.3.22", path = "../profile-bee-tui", optional = true }
profile-bee-common = { version = "0.3.23", path = "../profile-bee-common", features=["user", "color"] }
profile-bee-symbols = { version = "0.3.23", path = "../profile-bee-symbols" }
profile-bee-tui = { version = "0.3.23", path = "../profile-bee-tui", optional = true }
anyhow = "1.0.42"
clap = { version = "4.0", features = ["derive"] }
tokio = { version = "1.18", features = ["macros", "rt", "rt-multi-thread", "net", "signal", "time", "process"] }
Expand All @@ -49,6 +49,8 @@ memmap2 = "0.9"
lru = "0.12"
prost = "0.13"
flate2 = "1"
tar = "0.4"
sha2 = "0.10"
strip-ansi-escapes = "0.2"
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls"] }
parking_lot = "0.12"
Expand Down
Loading
Loading