mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
a3b7f47d17
Diagnosing "why is this title spending its time in the interpreter" currently means issuing eight TCP commands by hand and correlating their JSON. That is enough friction that it does not get done, and when it is done by someone without the runtime's internals in their head the numbers get misread -- #72 is a live example: an empty phase_hot was read as a possible bad query when it in fact meant nothing native was executing at all. stall_report.py collapses that into one command and one pasteable report, usable against any title on any port: [1] Is the overlay cache actually BEING USED, or just present on disk? dispatch_native vs dispatch_interp_fallback, stale_blocked, the autocompile degraded channel, and shard ok/fail/skipped counts. [2] When code IS interpreted, is it chaining or thrashing? dirty_ram insns_run/blocks_run = instructions per dispatcher round-trip, with the kernel-window-is-per-block-by-design caveat stated inline so a low ratio there is not misread as a bug. [3] Where did the wall-clock actually go? The largest host_us gaps in the always-on PC-sample ring, each with the guest cycles that advanced across it. That ratio separates three failure shapes that look identical in a frame-time graph: CPU kept up (gap is GPU/present/vsync), CPU-bound but executing, and emu thread not running at all. [4]-[6] phase shares, hottest interpreted PCs tagged kernel vs above-floor, and phase_hot deltas for both the native and static sets. PASSIVE RING CONSUMER by construction, per the project's observability rule: it never arms a trace, never pauses, never single-steps. Everything is a cumulative counter (two snapshots subtract to a window) or a read of a ring that has been recording since process start, so attaching late still sees the event. `snap` reports cumulative; `run --secs N` reports deltas. Two caveats are printed in the output rather than left to be rediscovered: current_func is a STATIC dispatch stamp and localizes without proving interpretation, and an empty native phase_hot means nothing native ran rather than a malformed query. Validated against a live Tomba 2 debug build (Release + PSX_DEBUG_TOOLS=ON, port 4515), both modes and the --out JSON artifact. Representative real output: dispatch_native 3,253,132 (97.16%) vs interp_fallback 95,047 (2.84%), 16,329 instructions per dispatcher round-trip, and one 68 ms gap at 0.46x realtime flagged in-exception. Development of the tool caught two defects in itself that way -- snap mode subtracted a snapshot from itself and reported zeros for everything, and non-ASCII output mojibaked on a cp1252 console -- both fixed before commit. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>