perf(debugger): sample probes in breakpoint conditions#8967
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
Overall package sizeSelf size: 6.36 MB Dependency sizes| name | version | self size | total size | |------|---------|-----------|------------| | import-in-the-middle | 3.2.0 | 104.26 kB | 843.44 kB | | opentracing | 0.14.7 | 194.81 kB | 194.81 kB | | dc-polyfill | 0.1.11 | 25.74 kB | 25.74 kB |🤖 This report was automatically generated by heaviest-objects-in-the-universe |
🎉 All green!🧪 All tests passed 🔗 Commit SHA: d869c02 | Docs | Datadog PR Page | Give us feedback! |
4776de7 to
eb0fd43
Compare
7f047cd to
bc04cb3
Compare
9aa4315 to
63aa918
Compare
BenchmarksBenchmark execution time: 2026-06-26 16:56:26 Comparing candidate commit d869c02 in PR branch Found 1 performance improvements and 0 performance regressions! Performance is the same for 2222 metrics, 63 unstable metrics.
|
63aa918 to
08a01ab
Compare
eb0fd43 to
5793b97
Compare
5b3deae to
fa6cdfa
Compare
5793b97 to
e2e691d
Compare
The probe sampling refactor in #8967 moved sampled probe tracking into the sampler buffer, but left behind the old snapshot probe index bookkeeping. Remove the dead resizeable ArrayBuffer path and Node.js version gate from the paused debugger handler.
fa6cdfa to
6894af5
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6894af5eed
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The probe sampling refactor in #8967 moved sampled probe tracking into the sampler buffer, but left behind the old snapshot probe index bookkeeping. Remove the dead resizeable ArrayBuffer path and Node.js version gate from the paused debugger handler.
1f351f5 to
75ba72e
Compare
BridgeAR
left a comment
There was a problem hiding this comment.
Nice, this is looking really great!
I have a few small nits, nothing blocking. The only question is about cross realm probes.
The cross realm aspect we are loosing is something I am uncertain about. Should we just keep the old approach when cross realm breakpoints are used? We can detect these, if I am not mistaken and could handle them accordingly.
75ba72e to
3f928f1
Compare
BridgeAR
left a comment
There was a problem hiding this comment.
LGTM, while I still believe it would be nice to keep the old logic as fallback for cross realm probes
Move probe sampling into generated breakpoint conditions so unsampled hits can avoid pausing the application. The devtools worker now reads sampled probe indexes from a shared buffer instead of evaluating conditions and sampling after every pause. Install a runtime sampler in the debuggee, track probe indexes in worker state, and clear sampler state when probes are removed. This keeps per-probe sampling, user conditions, and the global snapshot sampling limit in the condition path. Add focused coverage for sampler expressions, breakpoint condition rebuilding, pause handling, overflow handling, and stale sampled probe indexes.
3f928f1 to
d869c02
Compare
The probe sampling refactor in #8967 moved sampled probe tracking into the sampler buffer, but left behind the old snapshot probe index bookkeeping. Remove the dead resizeable ArrayBuffer path and Node.js version gate from the paused debugger handler.
Move probe sampling into generated breakpoint conditions so unsampled hits can avoid pausing the application. The devtools worker now reads sampled probe indexes from a shared buffer instead of evaluating conditions and sampling after every pause. Install a runtime sampler in the debuggee from the debugger bootstrap, hand the shared buffer to the worker, and uninstall it on cleanup so the sampler survives debugger stop/start. Track probe indexes in worker state and clear per-probe sampler state when a probe is removed. This keeps per-probe sampling, user conditions, and the global snapshot sampling limit in the condition path. Rework the sirun debugger benchmark to exercise the new condition path: add a second breakpoint target, make the startup-guard share and operation counts configurable, drop the install-only variant, and honor per-variant iteration counts in the overview collector. Add focused coverage for sampler expressions, breakpoint condition rebuilding, pause handling, overflow handling, stop/start, and stale sampled probe indexes.

What does this PR do?
Moves Node.js debugger probe sampling into generated breakpoint conditions so unsampled probe hits can avoid pausing the debuggee process. The debugger bootstrap installs a runtime sampler in the debuggee process and shares a buffer with the devtools worker. Breakpoint conditions make the sampling decision inline and record sampled probe indexes into that buffer; the worker then only processes the probes the condition path sampled.
Motivation
Probe sampling was previously decided after V8 had already paused the application and control had moved to the devtools worker. That meant probes dropped by per-probe sampling or the global snapshot sampling limit could still add pause overhead. Moving the decision into the breakpoint condition makes the common unsampled case cheaper.
Additional Notes
Added focused tests for
probe_sampler, breakpoint condition rebuilding, sampler state cleanup on probe removal, pause handling with sampled probe indexes, overflow handling, and stale/inconsistent sampled probe state.Known limitations
Breakpoint conditions read the sampler from the realm-local
globalThis, so a probe whose code runs in a separate V8 realm (e.g. avm.runInContextscript) can't reach it and silently won't fire, rather than crash.In practice the only affected user is one who runs application code in a vm context with an absolute-path filename and places a probe on a line inside it:
This only narrows an already-degraded, undocumented path for Dynamic Instrumentation: even before this change such probes produced correlation-less snapshots, because
global.requiredoesn't exist in the vm realm. Test Optimization's failing-test replay is unaffected, as it runs in a separate worker that sets unconditional breakpoints.