mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-28 19:07:47 -04:00
Document frame ring schema and limits of hitch attribution
This commit is contained in:
@@ -1,25 +1,33 @@
|
||||
# Always-on host wall-time rings (hitch attribution)
|
||||
|
||||
A gameplay hitch is wall time the emulation thread did not spend running the guest. These rings
|
||||
record where it went, continuously from process start in every build, so a probe never arms
|
||||
A gameplay hitch is an unusually long frame, whether from guest execution, host work, or waiting.
|
||||
These rings record where the time went, continuously from process start in every build, so a probe never arms
|
||||
anything: it queries a window that already happened.
|
||||
|
||||
| Ring | TCP command | Holds |
|
||||
|------|-------------|-------|
|
||||
| frame stamps | `frame_wall_ring {"from":SEQ,"n":N}` | one `[guest frame, wall us, interpreter insns (low 32 bits)]` per guest frame, 131072 frames (~36 min at 60 Hz) |
|
||||
| frame stamps | `frame_wall_ring {"from":SEQ,"n":N}` | flat `f` array with `stride: 6`: `[guest frame, wall us, interpreter insns, static checks, process page faults, process read KiB]`; counters use their low 32 bits; 131072 frames (~36 min at 60 Hz) |
|
||||
| spans | `host_span_ring {"from":SEQ,"n":N}` | `[seq, kind, t0_us, dur_us, frame, emu, arg]` for every named blocking-capable operation of 50 us or more, 65536 spans |
|
||||
| host CPU sampler (debug-tools builds) | `host_profile {"frame_lo":A,"frame_hi":B}` | 1 kHz instruction-pointer samples of the emulation thread, 1 Mi samples (~17 min), with per-module totals for samples outside the exe |
|
||||
|
||||
Wall time is microseconds since the first ring call. `emu` is 1 for the emulation thread, 0 for a
|
||||
worker (compiler child, publication preparer).
|
||||
|
||||
Readers and writers use nonblocking slot ownership. A contended sample may be dropped or skipped;
|
||||
readers only return fully published records from the requested ring generation. A missing frame
|
||||
stamp leaves an interval spanning multiple frames: do not report that interval as one long frame.
|
||||
Legacy frame captures had three or four columns and no `stride`; consumers must identify their
|
||||
layout before interpreting them. Process counters include worker threads, and page faults include
|
||||
soft faults, so neither counter alone proves a blocking disk read.
|
||||
|
||||
Span kinds (`runtime/include/host_span_ring.h`): `autocapture_tick`, `provider_poll`,
|
||||
`publish_commit`, `loader_rescan`, `dll_register`, `lazy_load` (a synchronous first map of a shard
|
||||
at a dispatch miss), `capture_on_dma`, `capture_before_dma`, `ac_request` (spawning the compiler),
|
||||
`ac_done_join`, `ac_prepare_image` (worker), `ac_child` (compiler lifetime, worker).
|
||||
`ac_done_join`, `ac_prepare_image` (worker), `ac_child` (compiler lifetime, worker),
|
||||
`overlay_dispatch`, `mod_work`, `frame_present`, and `disc_read` (cooked or raw sector read).
|
||||
|
||||
Reading a hitch: per frame, `wall delta - sum(emulation-thread spans overlapping the frame)` is
|
||||
the time no span explains; then ask the host sampler for that frame window. A title's report tool
|
||||
Reading a hitch: per frame, subtract the union of overlapping emulation-thread spans from the wall
|
||||
delta to find the time no span explains; nested spans must not be counted twice. Then ask the host sampler for that frame window. A title's report tool
|
||||
joins them (`LegendOfDragoonRecomp/tools/lod_hitch_report.py`).
|
||||
|
||||
Findings the rings produced (LoD, 2026-10-12): a toolchain staged from another emitter than the
|
||||
|
||||
Reference in New Issue
Block a user