Elide’s native runtime supports standard diagnostic files and tools. Start a
capture with a short Elide flag, or use its Native Image VM equivalent. Discover
the options with elide help instruments; they are hidden from everyday help.
| Question | Capture | Inspect with |
|---|---|---|
| What happened during execution? | --jfr=run.jfr | JDK jfr |
| What is retained in the managed heap? | --heap-dump=heap.hprof | VisualVM |
| What is a running process doing? | jcmd PID | JFR, heap dumps, and thread stacks |
| Where does runtime-compiled code spend CPU time? | --jitdump=DIR and perf record | Linux perf inject and perf report |
Captures are opt-in. JMX server and native memory tracking (NMT) remain disabled. Heap dumps cover the managed VM heap, not all Rust or native allocations.
Before you start
Use a native Elide executable and put instrument flags before guest arguments
introduced by -- or -m module. They apply to run and explicit scripts,
snippets, or modules—not arbitrary tool commands. Paths may be relative or
absolute; quote paths containing spaces and choose writable output locations.
Download the tools you need:
- GraalVM JDK downloads — provides
jfrandjcmd. Use a JDK matching Elide’s GraalVM toolchain when possible. - VisualVM downloads — standalone heap viewer for Linux, macOS, and Windows. The download page includes launch instructions; see also Getting Started.
- Linux perf installation and JIT profiling
— install
perfthrough your Linux distribution and follow the jitdump workflow below. On WSL2, use tooling compatible with the running WSL kernel.
On Linux/macOS, point these commands at your extracted installations. This makes the short commands used throughout this guide available in the current shell:
export JAVA_HOME=/absolute/path/to/graalvm
export VISUALVM_DIR=/absolute/path/to/visualvm
export PATH="$JAVA_HOME/bin:$VISUALVM_DIR/bin:$PATH"
java -version
jfr --version
jcmd -l
# Linux only, when using jitdump:
perf versionIf VisualVM cannot find Java, launch it with
visualvm --jdkhome "$JAVA_HOME" --openfile heap.hprof. On Windows, use the
download’s bin/visualvm.exe; on macOS, the download page also offers an app bundle.
Live jcmd attach is supported on Linux and macOS, not Windows;
run it as the same OS user as Elide. Jitdump requires a Linux PGO release build
and a Linux perf installation with JIT injection support.
These native flags cannot reconfigure a hosting JVM that is already running.
In JVM mode, pass the JVM’s supported monitoring options to java before startup.
See the CLI Reference for exact flag equivalents and scope.
Record execution with JFR
elide --jfr=run.jfr run app.js
jfr summary run.jfr
jfr print --json run.jfrThe JDK jfr command reference
describes event filters, summaries, and other file-inspection commands.
--jfr uses the profile settings and saves the recording on normal exit.
Choose the default preset or a custom .jfc file with --jfr-settings:
elide --jfr=run.jfr --jfr-settings=default run app.js
# Equivalent VM spelling for the profile preset:
elide -XX:StartFlightRecording=filename=run.jfr,settings=profile,dumponexit=true run app.jsJFR filenames and settings cannot contain commas or double quotes through the
alias. Elide emits a dev.elide.Execution event with the invocation’s exit code:
jfr print --json --events dev.elide.Execution run.jfrCustom events use the dev.elide namespace and the Elide category. Recording
does not start an OpenTelemetry exporter; OpenTelemetry integration is future work.
Inspect the managed heap
elide --heap-dump=heap.hprof run app.js
visualvm --openfile heap.hprofElide captures the heap before engine teardown on normal exit. In VisualVM, inspect class and instance counts, then explore retained objects and references. You can collect both artifacts in one invocation:
elide --jfr=run.jfr --heap-dump=heap.hprof run app.jsTo request a dump on out-of-memory error instead:
elide --heap-dump-on-oom=oom.hprof run app.js
# Equivalent VM spelling:
elide -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=oom.hprof run app.jsThe separate VM option -XX:+DumpHeapAndExit captures the initial heap; it
does not replace Elide’s exit-time --heap-dump. Modern JDKs do not include the
old jhat heap browser: use a dedicated HPROF reader such as VisualVM.
Capture a running process
Find the process with jcmd -l, then substitute its PID below. Run these commands
while the workload is still running:
PID=12345
jcmd "$PID" help
jcmd "$PID" JFR.start name=profile settings=profile
jcmd "$PID" JFR.check
jcmd "$PID" JFR.dump name=profile filename=live.jfr
jcmd "$PID" JFR.stop name=profile
jcmd "$PID" GC.heap_dump live.hprof
jcmd "$PID" Thread.printUse jcmd "$PID" help COMMAND for supported parameters. Prefer absolute output
paths when the target has a different working directory. Native Image may write
thread stacks to the target’s stderr, so inspect its logs too.
The JDK jcmd reference
describes the tool; the target’s own help output is authoritative for which
commands its Native Image build supports.
Dump a live recording before forcibly stopping a process. SIGKILL and Elide’s hard timeout cannot finalize recordings. Normal-exit JFR/heap finalization failures produce a nonzero status while preserving an existing workload failure.
Profile JIT-compiled code on Linux
Linux PGO release images include runtime debug-info support but do not write jitdump files by default. Enable capture for a workload long enough to compile and execute hot guest functions:
perf record -k 1 --call-graph fp -o perf.data -- \
elide --jitdump=./jitdump run app.js
perf inject -j -i perf.data -o perf.jit.data
perf report -i perf.jit.data-k 1 selects the clock required for JIT injection. Keep the jitdump directory
and its jit-<pid>.dump file until injection completes. Injection produces
synthetic ELF objects for runtime-compiled code; the report should resolve hot
guest symbols from jitted- objects. Jitdump is perf metadata, not a JFR recording.
The VM equivalent is -XX:+RuntimeJitdump -XX:RuntimeJitdumpDir=DIR.
-XX:-RuntimeJitdump explicitly disables writing. Other builds omit this capability;
build it from source on Linux with ./builder build --release --pgo.
For AOT symbolization, make the matching distribution’s internal/elide.debug
discoverable to perf, for example through its build-ID cache. Full stack unwinding
across Rust/native libraries also depends on their compilation settings.
GraalVM can warn and continue when jitdump initialization or writing fails. A zero workload exit status is not enough: check that the dump exists, injection succeeds, and the report contains the expected guest symbols. If perf recording is denied, check the host’s profiling permissions rather than disabling security controls globally. WSL2 can support this workflow, but profiler availability and kernel support depend on the installation.
Verification and operational limits
The repository’s monitoring smoke suites generate fresh artifacts and open them
with their real readers: JDK jfr summary and jfr print --json, VisualVM’s
headless heap reader when configured, and perf inject followed by a symbolized
perf report. They also check the custom execution event and complete JIT code
records. The Linux PGO build passed all these checks on WSL2.
To repeat the checks from a checkout, set absolute paths for the built executable and the installed tools. Both jitdump and perf checks are explicitly opt-in:
export ELIDE_TEST_BINARY=/absolute/path/to/elide
export JAVA_HOME=/absolute/path/to/graalvm
export VISUALVM_HEAP_JAR=/absolute/path/to/visualvm/visualvm/modules/org-graalvm-visualvm-lib-jfluid-heap.jar
bun test --timeout 120000 tools/test/smoke/instruments.test.mts
ELIDE_TEST_JITDUMP=yes ELIDE_TEST_PERF=yes \
bun test --timeout 180000 tools/test/smoke/jitdump.test.mtsSuccessful file inspection establishes functional compatibility, not negligible overhead. Default-off jitdump still adds reachable code and metadata; measure equivalent builds on bare-metal Linux before drawing performance conclusions. Heap dumps and recordings can be large and expose application data, executable code, and source metadata. Store them privately and budget capture time and disk space before using them on a production workload.