Files
psxrecomp/docs
Matthew Stanley a3b7f47d17 tools: add stall_report.py, one-command interp/stall attribution
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>
2026-08-10 12:58:23 -07:00
..
2026-07-29 03:18:10 -04:00
2026-08-08 20:25:32 -04:00
2026-08-07 01:43:04 -04:00
2026-07-29 03:18:10 -04:00
2026-08-08 12:28:05 -04:00
2026-08-07 01:43:04 -04:00
2026-07-29 03:18:10 -04:00
2026-07-29 03:18:10 -04:00
2026-08-09 22:24:48 -04:00
2026-07-29 03:18:10 -04:00
2026-07-29 03:18:10 -04:00
2026-07-29 03:18:10 -04:00
2026-08-09 22:24:48 -04:00
2026-07-29 03:18:10 -04:00
2026-07-29 03:18:10 -04:00
2026-08-07 01:43:04 -04:00