GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — Keep monitoring dispatch and event metadata interpreter-local by youknowdot · Pull Request #9439 · RustPython/RustPython Conversation
|
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews: auto_review: drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
📦 Library DependenciesThe following Lib/ modules were modified. Here are their dependencies: [x] lib: cpython/Lib/profile.py dependencies:
dependent tests: (1 tests)
[ ] test: cpython/Lib/test/test_free_threading (TODO: 1) dependencies: dependent tests: (no tests depend on free_threading) Legend:
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Merging this PR will degrade performance by 19.03%
Warning Please fix the performance issues or acknowledge them on CodSpeed. Performance Changes
Tip Investigate this regression by commenting Comparing Footnotes
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
hmm, let's check performance before merge @codspeedbot explain performance drop |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Why performance droppedThis is a real regression, not noise. All of it comes from f8a7823 ("Keep monitoring dispatch in interpreter-local state"):
What the flamegraph shows (
|
| c672599 | f8a7823 | |
|---|---|---|
Interpreter loop self time (run_until → run_until_inner) |
366.6 ms | 534.0 ms |
monitoring::dispatch_operation self time |
— | 175.8 ms |
mem::replace<Option<u32>> (inlined) |
— | 39.3 ms |
| Total | 1.3 s | 1.7 s |
The float, list and call code costs the same in both runs (e.g. default_dealloc<PyFloat> 67.9 → 67.2 ms, PyFloat::into_ref 31.7 → 31.8 ms). The added time is all overhead in the dispatch loop, even though no monitoring tool is active.
A function call before every instruction (crates/vm/src/frame.rs:3909):
let mut virtual_dispatch = if PREPARE_GENERATOR { None } else { monitoring::dispatch_operation(vm, self.code, idx) };
dispatch_operation (sys/monitoring.rs:718) is not inlined. Even its fast path (vm.state.monitoring_events.load() == 0) costs a call, a pointer chase through vm.state and an atomic load per instruction. It also returns an Option<(MonitoringInstruction, Instruction)> that the loop then branches on. On main, the loop goes straight to read_unit_from. This adds extra live values in the hottest loop, which also explains why the loop's own self time grew by ~45%.
Extra writes per instruction in execute_instruction (frame.rs:4665-4666):
let index = self.lasti().saturating_sub(1); self.monitoring_previous = self.monitoring_current.replace(Some(index));
This re-loads lasti, even though the loop already holds idx, and writes two Option<u32> frame fields on every instruction, monitored or not.
Smaller additions: the virtual_line/legacy_line_processed checks and the DispatchMode/caches tuple on the decode path. Each one is cheap, but they all sit in the loop.
dispatch_operation into an #[inline(always)] check on monitoring_events == 0 and a #[cold] #[inline(never)] slow path. Better still, follow CPython: check instrumentation only at RESUME, backward jumps or the eval breaker, and keep a frame-local "monitored" flag. The plain path would then match main.monitoring_previous/monitoring_current only in monitored mode, and take the index from idx instead of re-loading lasti. If the generator-close LINE fix (f1c31d7) needs the previous position in the normal path too, it could be saved only when a frame suspends instead of on every instruction.main should bring these benchmarks back to their baseline.I haven't changed any code on the branch. Comment @codspeedbot try making the monitoring fast path zero-cost when no tool is active and I'll prototype the fix and benchmark it.
Was this response helpful? React with 👍 or 👎 to help us improve CodSpeedBot.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Preserve original RustPython#9439 ancestry and the reviewed float-power integration while preparing its functionality split. Assisted-by: OpenAI Codex: model version unavailable
Extract the six canonical library-only modules from #9439. Regenerated with scripts/update_lib from CPython d220409a13b77de7a6c30abe16ea90db01528edc. Assisted-by: OpenAI Codex: model version unavailable Co-authored-by: Codex <[email protected]>
Extract the syslog lock and whole canonical free-threading test from #9439. Regenerate the test with scripts/update_lib from CPython d220409a13b77de7a6c30abe16ea90db01528edc. Assisted-by: OpenAI Codex: model version unavailable Co-authored-by: Codex <[email protected]>
Extract mmap cursor and sequence behavior plus its whole canonical free-threading test from #9439. Regenerate the test with scripts/update_lib from CPython d220409a13b77de7a6c30abe16ea90db01528edc. Assisted-by: OpenAI Codex: model version unavailable Co-authored-by: Codex <[email protected]>
Extract CSV reader synchronization with its PyOperation facade and float-error helper from #9439. Include the whole canonical free-threading CSV test regenerated by scripts/update_lib from CPython d220409a13b77de7a6c30abe16ea90db01528edc. Assisted-by: OpenAI Codex: model version unavailable Co-authored-by: Codex <[email protected]>
Extract dictionary insertion and setdefault re-probing from #9439 with its five structural fixtures and whole canonical free-threading test. Regenerate the Lib file with scripts/update_lib from CPython d220409a13b77de7a6c30abe16ea90db01528edc. Assisted-by: OpenAI Codex: model version unavailable Co-authored-by: Codex <[email protected]>
Extract the independent code-source, clone, co_code and fallible decoding foundation from #9439. Interpreter-local monitoring dispatch remains in the dependent original PR. Assisted-by: OpenAI Codex: model version unavailable Co-authored-by: Codex <[email protected]>
Preserve original RustPython#9439 ancestry and the reviewed float-power integration while preparing its functionality split. Assisted-by: OpenAI Codex: model version unavailable
a2c7122 to
fac8d18
Compare
|
TODO: need review |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
95a4916 to
bbfa0c6
Compare
Preserve the final monitoring feature delta from 95a4916 on current main. Before cleanup, the rebased tree exactly matches Git merge-tree, avoiding obsolete intermediate prerequisites. Remove four redundant production tail drops while retaining named retired owners outside lock scopes. Preserve all operand, callback and early-release order. No test content changed relative to the prior feature. Assisted-by: OpenAI Codex:model-version-unavailable
Inline the no-events guard without pulling metadata preparation into the ordinary opcode loop. Reject direct yields using the suspended frame instruction provenance before the bounded yield-from shape walk. Preserve all monitored dispatch and unproven-position fallbacks. Assisted-by: OpenAI Codex:model-version-unavailable
bbfa0c6 to
2845454
Compare
Cache only the last bounded-walk-validated suspension offset. Keep dynamic SEND specialization, stack, receiver, and monitoring guards, and preserve the cache when the same code frame is materialized. Assisted-by: OpenAI Codex:model-version-unavailable
Keep ordinary dispatch separate from observed execution, preserve prefix state across mode changes, and reuse per-thread safepoint requests for monitoring activation. Retain displaced slot owners outside registry locks. Assisted-by: OpenAI Codex:model-version-unavailable
The intermediate snapshot is required to release the registry lock before a failed atomic snapshot can finalize an exception. Keep displaced slots alive with lexical ownership instead of an explicit drop. Assisted-by: OpenAI Codex:model-version-unavailable
Assisted-by: OpenAI Codex:model-version-unavailable
Restrict legacy c events to native functions and method descriptors, binding each descriptor event independently. Route native-call specializations through a local observed CALL with adaptive writes suppressed, without changing the unobserved dispatch body or shared bytecode. Preserve full static type names in descriptor repr and remove the profile output expected failure. Assisted-by: Codex:unknown
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.