feat(profile): HOS_HLE_STATS=1 counts HLE, host-call and NVN export calls #153

Merged
HumanBean merged 10 commits from klimovich008/Longshot:feat/hle-call-counters into main 2026-11-14 20:47:04 +00:00
Contributor

Port of NotRexed/Hookshot#2580 (draft there). It went through five gpt-6.1-sol review rounds, as that PR's description says. Each round's findings were fixed, and the last round found none. It has no GitHub reviews. The commits are the same, rebased onto Longshot main, plus one that gives the test Longshot's file names.

Why

The CPU profile's calls column came from a local patch that nobody else could rebuild. With this PR, anyone can count how often each HLE function, host call and NVN export runs, behind a switch that is off by default.

What changed

  • host/hos.h: the HLE(sym) macro counts entries in a tail-called arm (hos_hle_counted). With counting off, an entry pays one flag test and a branch.
  • host/hos_hostcall.c: logs hle: blocks about every 5 s, each stamped with the monotonic clock times it covers (begin_ns, end_ns). Host calls are counted in a64_call_miss and a64_lookup_host. The host-call table is read under its lock and the counters are published atomically. If the report thread can't start, counting stays off.
  • host/hos_main.c: turns counting on before the game starts.
  • host/nvn_native.c: counts SDK export calls in nvn2_dispatch.
  • scripts/cpu_report.py (--calls):
    • joins only complete, timed blocks inside the measured window to native frame returns over the same clock span;
    • estimates time per call as sampled occupancy, from the same run's HOS_SAMPLE_ALL stacks;
    • reads logs without timestamps for rates only, with no per-frame or per-call figures.
  • scripts/crit.py: names an HLE body that wasn't inlined after its imp_<sym> entry.
  • docs/development.md, docs/cpu-profile.md: the switch and how to collect a counting run. The profile's existing calls and per-call columns predate the clock-checked joins, so they are marked for regeneration. This PR does not recompute them.
  • tests/test_hle_stats.py, tests/test_cpu_report.py: switching on and off, NVN exports, 32-bit wrap, concurrent callers with the reporter running, a failed thread start, the complete-block and window checks, and nine broken variants that must be caught.

Flags and settings

Flag What it does Default now Recommendation Helps on Doesn't help on Untested on
HOS_HLE_STATS=1 Logs hle: call counts about every 5 s, with clock boundaries, for cpu_report.py --calls off Keep off. It is a profiling switch, and performance numbers come from runs without it Profiling Play Linux, web build

Measurements

main: 839e85ff (2026-11-13)
this PR: feat/hle-call-counters @ a4ce1b54, merged onto 839e85ff for the build.
Why the numbers still hold on main 5e072fc8: 839e85ff is the team's current measurement base. Since then, main's changes to the files this PR touches (host/hos.h, host/hos_main.c, host/nvn_native.c) give some log lines a level (hos_log_at). None of them is on the HLE entry path, and both merges (525fcf60 with 514591a3, 055a8fac with 5e072fc8) applied without conflicts in this PR's files. Main's other changes affect this PR's two arms and main alike.
Hardware: AMD RX 9070 XT (Adrenalin 26.10.2), Ryzen 7 5700X3D, 64 GB, Windows 11
Scene: Hyrule Field, fast camera turn (the standard test); 16:9 (HOS_WINDOW_SIZE=1280x720, HOS_ASPECT=1.7778), HOS_FPS_MAX=240, HOS_FPS_LOG=1, the fixed test profile test-profile-169.ini, no upscaler or frame generation
Method:

  • Each run has a 20 s window from the load, with warm caches.
  • Three arms alternate pair by pair: main, this PR with counting off, and this PR with HOS_HLE_STATS=1.
  • A run counts only if:
    • its game clock reads 1.000 ± 0.01, judged on clock intervals wholly inside the window;
    • it has a complete measured window.
  • A pair counts only if all three of its runs count.
  • The base stalls in this scene now and then. In about a third of the runs a clock interval inside the window reads 0.67 to 0.95, in every arm. Two batches were needed to reach 3 complete pairs:
    • batch b, 21:05–21:30Z;
    • batch c, 21:31–21:48Z.
  • The table uses the first three complete pairs in run order: b1 (21:21–21:26Z), c0 (21:37–21:41Z) and c1 (21:41–21:44Z). The fourth complete pair, c2, is left out.
  • Rejected runs:
    • batch b, pair 0: the counting-on run and the main run, each for a clock interval off speed inside the window (main's read 0.787).
    • batch b, pair 2: the main run, for a clock interval off speed (0.673).
    • Warm-up runs b-warm0-1 and b-warm2-0 had no complete measured window. Warm-up runs are never in the table.
  • The exe and the renderer DLL both differ from main's. The DLL is rebuilt because it includes host/hos.h.
    • main: longshot.exe 6dc5a7f0, longshot_vk.dll 8eb6d56d
    • this PR: longshot.exe ab2af78d, longshot_vk.dll ce3c0a8d
      How to reproduce: from claude-perf, python -I std_test.py --runtime <this PR> --name <n> --arm stats=HOS_HLE_STATS=1 --arm main@<main runtime>= --pairs 3 --options-ini test-profile-169.ini
3 pairs (medians) main @ 839e85ff this PR @ a4ce1b54, counting off this PR @ a4ce1b54, HOS_HLE_STATS=1
fps 65.39 66.74 65.29
CPU ms a frame 60.70 61.49 62.72
game clock 1.000, 1.000, 1.001 1.001, 1.001, 1.001 1.000, 1.000, 1.002
p99 frame, ms 22.32 20.47 20.33
worst frame, ms 603.2 59.4 473.9
frames over 50 / 100 / 250 ms (all runs) 5 / 3 / 1 3 / 0 / 0 2 / 1 / 1
pair      main fps/CPU ms   off fps/CPU ms   on fps/CPU ms
b1        65.39 / 60.696    66.79 / 60.407   64.34 / 62.719
c0        66.39 / 60.029    66.74 / 61.493   65.29 / 62.871
c1        63.19 / 61.474    63.09 / 63.590   66.59 / 61.808

Diagnostic. With 3 pairs, std_test labels any effect under 5% "diagnostic", and every effect here is under 5%:

  • Counting off against main: CPU ms a frame differs by -0.29, +1.46 and +2.12 in the three pairs (median +1.46, +2.4%), and fps by +1.40, +0.35 and -0.10.
  • Counting on against off: CPU ms a frame differs by +2.31, +1.38 and -1.78 (median +1.38, +2.2%), and fps by -2.45, -1.45 and +3.50.

Both comparisons change sign between pairs, so these three pairs resolve no cost either way. The single slow frames over 250 ms (603 ms on main, 474 ms with counting on) are the base's stalls; main has them too.

Reports with counting on: every counting-on run logged complete, clock-stamped hle: blocks (12 to 15 per run, about every 5.0005 s, each starting at the previous one's end_ns). None logged "could not start".

The Hookshot PR's earlier measurement (32:9, Hookshot 46780503, 8 pairs, no measurable cost with counting off) is in its description. It is not comparable with the 16:9 numbers here.

Testing

Tested:

  • On this branch at 055a8fac, which is a4ce1b54 merged with main 5e072fc8:
    • python -I -B tests/run_all.py --jobs 4 (Windows, llvm-mingw 20261104): 521 passed, 5 failed, 36 skipped. All 5 fail the same way on a clean checkout of main 5e072fc8 on this PC (520 passed, 5 failed, 36 skipped there): tests/test_framegen_resources.py, tests/test_module_ids.py, tests/test_pad_layout.py, tests/test_oot_state_tap.py, tests/test_tested_configurations.py.
    • The changed host files (host/hos_hostcall.c, host/hos_main.c, host/nvn_native.c) syntax-compile on Linux with gcc 15.2 (Ubuntu, WSL) and the build's Linux host flags (-I host/posix -D_GNU_SOURCE, x86-64-v3, A64_POLLING, A64_WRITE_TRACK), and on Windows with clang targeting MSVC. Not linked on Linux, and no Linux game build.
  • At a4ce1b54:
    • tests/test_hle_stats.py passes with llvm-mingw clang++ and with g++ (MSYS2 UCRT64);
    • tests/test_cpu_report.py passes;
    • every host/*.c syntax-compiles with llvm-mingw, except five that need third-party headers not installed here (dav1d, zstd, opus, ffmpeg). None of the five use the counters.
  • In the game: the measurements above. Windows, RX 9070 XT, built from 839e85ff with this PR merged.

Not tested:

  • The per-call time estimates have not run on real data. The A/B above ran without the sampler. The earlier counting run on Hookshot sampled mostly the load, and cpu_report.py --calls reported the estimates as unavailable instead of guessing, which is the intended behaviour. The estimate path is covered by the test fixtures only.
  • Linux beyond the syntax compile above: no Linux link, game build or run here. A tester is asked below.
  • The web build.

Needs other testers:

  • Linux, any GPU: the host builds, and HOS_HLE_STATS=1 logs complete hle: blocks about every 5 s while the game runs normally; unset, no hle: lines, expecting both (T-DWGM)

Screenshots

Nothing on screen.

Risk and rollback

The HLE(sym) macro is on every HLE entry's path. With counting off, the only change is one flag test, and neither measurement shows a cost (the Longshot A/B is diagnostic at 3 pairs). With it on, an extra thread wakes about every 5 s and every counted call does an atomic increment. Reverting the commits removes it all.

Reviewer notes

Start with hos.h (the macro) and hos_hostcall.c (the counters and the report thread). The calls and per-call columns already in docs/cpu-profile.md are left for a regenerated profile. This PR only marks them.

Issues

None.

Checklist

For everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description).
  • Rebased on current main.
  • python -I -B tests/run_all.py run and passing (any failure that also fails on main is named above).
  • Tested in the game, or what wasn't is named under Testing.
  • Testing filled in: what was tested, what wasn't, and what needs other testers (with test requests).
  • Measured: main and this PR at named commits, on the same PC, scene and settings, at least 2 interleaved runs each, the median reported.
  • No game files, dumps, build output or generated files.
  • third_party/ untouched (a new folder with a PROVENANCE.md instead).
  • The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled.

If applicable

  • AI assistance recorded with Assisted-by: / Co-Authored-By: trailers.
  • Flags noted, and the switch reference updated (docs/development.md, the README).
  • Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. Windows: built into the measured exe. Linux: the changed host files syntax-compile with gcc 15.2 and the build's Linux flags (Testing); the full Linux build is T-DWGM.
  • A check under tests/ that reads changed source updated in this PR, not weakened.
  • Docs updated.

🤖 Generated with Claude Code

Port of [NotRexed/Hookshot#2580](https://github.com/NotRexed/Hookshot/pull/2580) (draft there). It went through five gpt-6.1-sol review rounds, as that PR's description says. Each round's findings were fixed, and the last round found none. It has no GitHub reviews. The commits are the same, rebased onto Longshot `main`, plus one that gives the test Longshot's file names. ## Why The CPU profile's calls column came from a local patch that nobody else could rebuild. With this PR, anyone can count how often each HLE function, host call and NVN export runs, behind a switch that is off by default. ## What changed - `host/hos.h`: the `HLE(sym)` macro counts entries in a tail-called arm (`hos_hle_counted`). With counting off, an entry pays one flag test and a branch. - `host/hos_hostcall.c`: logs `hle:` blocks about every 5 s, each stamped with the monotonic clock times it covers (`begin_ns`, `end_ns`). Host calls are counted in `a64_call_miss` and `a64_lookup_host`. The host-call table is read under its lock and the counters are published atomically. If the report thread can't start, counting stays off. - `host/hos_main.c`: turns counting on before the game starts. - `host/nvn_native.c`: counts SDK export calls in `nvn2_dispatch`. - `scripts/cpu_report.py` (`--calls`): - joins only complete, timed blocks inside the measured window to native frame returns over the same clock span; - estimates time per call as sampled occupancy, from the same run's `HOS_SAMPLE_ALL` stacks; - reads logs without timestamps for rates only, with no per-frame or per-call figures. - `scripts/crit.py`: names an HLE body that wasn't inlined after its `imp_<sym>` entry. - `docs/development.md`, `docs/cpu-profile.md`: the switch and how to collect a counting run. The profile's existing calls and per-call columns predate the clock-checked joins, so they are marked for regeneration. This PR does not recompute them. - `tests/test_hle_stats.py`, `tests/test_cpu_report.py`: switching on and off, NVN exports, 32-bit wrap, concurrent callers with the reporter running, a failed thread start, the complete-block and window checks, and nine broken variants that must be caught. ## Flags and settings | Flag | What it does | Default now | Recommendation | Helps on | Doesn't help on | Untested on | |---|---|---|---|---|---|---| | `HOS_HLE_STATS=1` | Logs `hle:` call counts about every 5 s, with clock boundaries, for `cpu_report.py --calls` | off | Keep off. It is a profiling switch, and performance numbers come from runs without it | Profiling | Play | Linux, web build | ## Measurements main: 839e85ff (2026-11-13) this PR: feat/hle-call-counters @ a4ce1b54, merged onto 839e85ff for the build. Why the numbers still hold on main 5e072fc8: 839e85ff is the team's current measurement base. Since then, main's changes to the files this PR touches (`host/hos.h`, `host/hos_main.c`, `host/nvn_native.c`) give some log lines a level (`hos_log_at`). None of them is on the HLE entry path, and both merges (525fcf60 with 514591a3, 055a8fac with 5e072fc8) applied without conflicts in this PR's files. Main's other changes affect this PR's two arms and main alike. Hardware: AMD RX 9070 XT (Adrenalin 26.10.2), Ryzen 7 5700X3D, 64 GB, Windows 11 Scene: Hyrule Field, fast camera turn (the standard test); 16:9 (`HOS_WINDOW_SIZE=1280x720`, `HOS_ASPECT=1.7778`), `HOS_FPS_MAX=240`, `HOS_FPS_LOG=1`, the fixed test profile `test-profile-169.ini`, no upscaler or frame generation Method: - Each run has a 20 s window from the load, with warm caches. - Three arms alternate pair by pair: main, this PR with counting off, and this PR with `HOS_HLE_STATS=1`. - A run counts only if: - its game clock reads 1.000 ± 0.01, judged on clock intervals wholly inside the window; - it has a complete measured window. - A pair counts only if all three of its runs count. - The base stalls in this scene now and then. In about a third of the runs a clock interval inside the window reads 0.67 to 0.95, in every arm. Two batches were needed to reach 3 complete pairs: - batch b, 21:05–21:30Z; - batch c, 21:31–21:48Z. - The table uses the first three complete pairs in run order: b1 (21:21–21:26Z), c0 (21:37–21:41Z) and c1 (21:41–21:44Z). The fourth complete pair, c2, is left out. - Rejected runs: - batch b, pair 0: the counting-on run and the main run, each for a clock interval off speed inside the window (main's read 0.787). - batch b, pair 2: the main run, for a clock interval off speed (0.673). - Warm-up runs b-warm0-1 and b-warm2-0 had no complete measured window. Warm-up runs are never in the table. - The exe and the renderer DLL both differ from main's. The DLL is rebuilt because it includes `host/hos.h`. - main: `longshot.exe` 6dc5a7f0, `longshot_vk.dll` 8eb6d56d - this PR: `longshot.exe` ab2af78d, `longshot_vk.dll` ce3c0a8d How to reproduce: from claude-perf, `python -I std_test.py --runtime <this PR> --name <n> --arm stats=HOS_HLE_STATS=1 --arm main@<main runtime>= --pairs 3 --options-ini test-profile-169.ini` | 3 pairs (medians) | main @ 839e85ff | this PR @ a4ce1b54, counting off | this PR @ a4ce1b54, `HOS_HLE_STATS=1` | |---|---|---|---| | fps | 65.39 | 66.74 | 65.29 | | CPU ms a frame | 60.70 | 61.49 | 62.72 | | game clock | 1.000, 1.000, 1.001 | 1.001, 1.001, 1.001 | 1.000, 1.000, 1.002 | | p99 frame, ms | 22.32 | 20.47 | 20.33 | | worst frame, ms | 603.2 | 59.4 | 473.9 | | frames over 50 / 100 / 250 ms (all runs) | 5 / 3 / 1 | 3 / 0 / 0 | 2 / 1 / 1 | ``` pair main fps/CPU ms off fps/CPU ms on fps/CPU ms b1 65.39 / 60.696 66.79 / 60.407 64.34 / 62.719 c0 66.39 / 60.029 66.74 / 61.493 65.29 / 62.871 c1 63.19 / 61.474 63.09 / 63.590 66.59 / 61.808 ``` **Diagnostic.** With 3 pairs, std_test labels any effect under 5% "diagnostic", and every effect here is under 5%: - Counting off against main: CPU ms a frame differs by -0.29, +1.46 and +2.12 in the three pairs (median +1.46, +2.4%), and fps by +1.40, +0.35 and -0.10. - Counting on against off: CPU ms a frame differs by +2.31, +1.38 and -1.78 (median +1.38, +2.2%), and fps by -2.45, -1.45 and +3.50. Both comparisons change sign between pairs, so these three pairs resolve no cost either way. The single slow frames over 250 ms (603 ms on main, 474 ms with counting on) are the base's stalls; main has them too. **Reports with counting on:** every counting-on run logged complete, clock-stamped `hle:` blocks (12 to 15 per run, about every 5.0005 s, each starting at the previous one's `end_ns`). None logged "could not start". The Hookshot PR's earlier measurement (32:9, Hookshot 46780503, 8 pairs, no measurable cost with counting off) is in [its description](https://github.com/NotRexed/Hookshot/pull/2580). It is not comparable with the 16:9 numbers here. ## Testing **Tested:** - On this branch at 055a8fac, which is a4ce1b54 merged with main 5e072fc8: - `python -I -B tests/run_all.py --jobs 4` (Windows, llvm-mingw 20261104): 521 passed, 5 failed, 36 skipped. All 5 fail the same way on a clean checkout of main 5e072fc8 on this PC (520 passed, 5 failed, 36 skipped there): `tests/test_framegen_resources.py`, `tests/test_module_ids.py`, `tests/test_pad_layout.py`, `tests/test_oot_state_tap.py`, `tests/test_tested_configurations.py`. - The changed host files (`host/hos_hostcall.c`, `host/hos_main.c`, `host/nvn_native.c`) syntax-compile on Linux with gcc 15.2 (Ubuntu, WSL) and the build's Linux host flags (`-I host/posix -D_GNU_SOURCE`, x86-64-v3, `A64_POLLING`, `A64_WRITE_TRACK`), and on Windows with clang targeting MSVC. Not linked on Linux, and no Linux game build. - At a4ce1b54: - `tests/test_hle_stats.py` passes with llvm-mingw clang++ and with g++ (MSYS2 UCRT64); - `tests/test_cpu_report.py` passes; - every `host/*.c` syntax-compiles with llvm-mingw, except five that need third-party headers not installed here (dav1d, zstd, opus, ffmpeg). None of the five use the counters. - In the game: the measurements above. Windows, RX 9070 XT, built from 839e85ff with this PR merged. **Not tested:** - **The per-call time estimates have not run on real data.** The A/B above ran without the sampler. The earlier counting run on Hookshot sampled mostly the load, and `cpu_report.py --calls` reported the estimates as unavailable instead of guessing, which is the intended behaviour. The estimate path is covered by the test fixtures only. - Linux beyond the syntax compile above: no Linux link, game build or run here. A tester is asked below. - The web build. **Needs other testers:** - Linux, any GPU: the host builds, and `HOS_HLE_STATS=1` logs complete `hle:` blocks about every 5 s while the game runs normally; unset, no `hle:` lines, expecting both (T-DWGM) ## Screenshots Nothing on screen. ## Risk and rollback The `HLE(sym)` macro is on every HLE entry's path. With counting off, the only change is one flag test, and neither measurement shows a cost (the Longshot A/B is diagnostic at 3 pairs). With it on, an extra thread wakes about every 5 s and every counted call does an atomic increment. Reverting the commits removes it all. ## Reviewer notes Start with `hos.h` (the macro) and `hos_hostcall.c` (the counters and the report thread). The calls and per-call columns already in `docs/cpu-profile.md` are left for a regenerated profile. This PR only marks them. ## Issues None. ## Checklist ### For everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`). - [x] Rebased on current `main`. - [x] `python -I -B tests/run_all.py` run and passing (any failure that also fails on `main` is named above). - [x] Tested in the game, or what wasn't is named under Testing. - [x] Testing filled in: what was tested, what wasn't, and what needs other testers (with test requests). - [x] Measured: main and this PR at named commits, on the same PC, scene and settings, at least 2 interleaved runs each, the median reported. - [x] No game files, dumps, build output or generated files. - [x] `third_party/` untouched (a new folder with a `PROVENANCE.md` instead). - [x] The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled. ### If applicable - [x] AI assistance recorded with `Assisted-by:` / `Co-Authored-By:` trailers. - [x] Flags noted, and the switch reference updated (docs/development.md, the README). - [x] Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. Windows: built into the measured exe. Linux: the changed host files syntax-compile with gcc 15.2 and the build's Linux flags (Testing); the full Linux build is T-DWGM. - [x] A check under `tests/` that reads changed source updated in this PR, not weakened. - [x] Docs updated. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The CPU profile's "calls a frame" and "us a call" columns (docs/cpu-profile.md,
scripts/cpu_report.py --calls) came from a local patch, so nobody else could
rebuild them. The HLE macro now keeps a counter per function, counted only
with HOS_HLE_STATS=1; a thread logs the counts of the last 5 s, with the host
calls' (counted in a64_call_miss as for HOS_HOSTCALL_STATS), in the "hle:"
lines cpu_report.py reads. Off by default: a call then costs a load and a
branch more.

Assisted-by: Claude Code
Co-Authored-By: Claude Opus 5.5 <[email protected]>
From review: the sdk's NVN exports (nvn2_dispatch) went to their host call
directly and were never counted; they now go through a64_call_miss when
HOS_HLE_STATS is on. The report printed 150 rows while moving every
baseline, so later rows lost their counts: it prints all of them. Counts
since the last report are taken unsigned, so a 32-bit count passing its
maximum is not skipped. The macro's counted arm is a tail call
(hos_hle_counted calls the body), so a leaf handler saves no registers
for it when the switch is off. cpu_report.py reads a summary's rows up
to the next summary, skipping other threads' lines logged in between.

Assisted-by: Claude Code
Co-Authored-By: Claude Opus 5.5 <[email protected]>
From review: with the HLE macro's counted arm, a body the compiler keeps out
of line is its own symbol, hle_<sym>. cpu_report.py's maps and crit.py's
import frames knew only imp_<sym>, so such a function's samples lost their
SDK name, description and call counts. The counter's own functions no longer
start with hle_, so that prefix means an HLE body only.

Assisted-by: Claude Code
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Assisted-by: Claude Code
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Truncating HLE names merges existing overloads in the call-count log. The
report then assigns their combined count to each full function, making
calls per frame and time per call incorrect.

Log one full name per row and retain the full name when joining profile
symbols. Cover two real overload names with different counts and reject a
mutation that restores truncation.

The actual producer/parser check reports 100/100 on the old code and 60/40
with the fix. The expanded fixture passes with GCC and llvm-mingw and catches
all seven broken variants. Both Windows compilers syntax-check the whole C
file using retained runtime headers. Full-suite and parent-feature off-path
performance checks remain pending.

Assisted-by: OpenAI Codex
Co-Authored-By: Codex <[email protected]>
Reporting fixes by Codex. Each `hle:` summary now carries its measured
monotonic span (begin_ns/end_ns) instead of a nominal 5 s; cpu_report.py
reads only complete blocks and joins them to native frame returns over
that same span, and per-call figures become estimated sampled occupancy
from the same run's timestamped stacks. The report reads the host-call
table under its lock and a failed thread start turns counting back off.
The docs flag the CPU profile's existing call columns for regeneration.

The default-off macro (hos.h), main's startup hook and nvn_native.c are
unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The parser now takes a block only when its rows match the head's count and total, and a row ends in ";".

Co-Authored-By: Claude Opus 5.5 <[email protected]>
test(hle_stats): Longshot's file names (longshot_env.h, longshot.exe, longshot.map)
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 8s
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
a4ce1b54ce
Assisted-by: Claude Code
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Merge remote-tracking branch 'origin/main' into feat/hle-call-counters
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 3s
Website / Website on Cloudflare (pull_request_target) Has been skipped
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
Website / Website on Cloudflare (pull_request) Has been cancelled
525fcf60d9
Author
Contributor

Merged main 514591a3 (525fcf60, no force-push). run_all: 463 passed, 4 failed, 67 skipped; all 4 also fail on main. First Longshot measurement: standard test at 16:9 on 839e85ff, 3 complete pairs across two batches (21:05–21:48Z), main against this PR with counting off and on. Diagnostic: every effect is under 5% and changes sign between pairs. Rejected runs are listed under Measurements. Opened Linux test request T-DWGM. The per-call estimates are still untested on a real run.

Merged main 514591a3 (525fcf60, no force-push). run_all: 463 passed, 4 failed, 67 skipped; all 4 also fail on main. First Longshot measurement: standard test at 16:9 on 839e85ff, 3 complete pairs across two batches (21:05–21:48Z), main against this PR with counting off and on. Diagnostic: every effect is under 5% and changes sign between pairs. Rejected runs are listed under Measurements. Opened Linux test request T-DWGM. The per-call estimates are still untested on a real run.
Merge main 5e072fc8 into feat/hle-call-counters
Some checks are pending
CI / Conventional Commit title (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Blocked by required conditions
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Blocked by required conditions
CI / Workflow lint (actionlint) (pull_request) Blocked by required conditions
Third-party parts / As their notes say (pull_request) Blocked by required conditions
Third-party parts / The same as upstream (pull_request) Blocked by required conditions
Website / Website on Cloudflare (pull_request) Blocked by required conditions
PR description / Description follows the template (pull_request_target) Successful in 5s
Website / Website on Cloudflare (pull_request_target) Has been skipped
055a8fac63
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Author
Contributor

Merged main 5e072fc8 (055a8fac, no force-push, no conflicts in this PR's files). run_all: 521 passed, 5 failed, 36 skipped; all 5 fail the same way on clean main 5e072fc8 here. The changed host files now also syntax-compile on Linux (gcc 15.2, the build's Linux host flags); the full Linux build stays with T-DWGM. Taking it out of WIP.

Merged main 5e072fc8 (055a8fac, no force-push, no conflicts in this PR's files). run_all: 521 passed, 5 failed, 36 skipped; all 5 fail the same way on clean main 5e072fc8 here. The changed host files now also syntax-compile on Linux (gcc 15.2, the build's Linux host flags); the full Linux build stays with T-DWGM. Taking it out of WIP.
klimovich008 changed title from WIP: feat(profile): HOS_HLE_STATS=1 counts HLE, host-call and NVN export calls to feat(profile): HOS_HLE_STATS=1 counts HLE, host-call and NVN export calls 2026-11-14 13:14:03 +00:00
monsterlag approved these changes 2026-11-14 16:17:22 +00:00
monsterlag left a comment

Independent Windows code/test review of 055a8fac63: no blocking findings.

Reviewed the disabled HLE-entry path, counter publication/bounds/wrap, report-thread start failure, NVN dispatch counting and complete clock-window joins in cpu_report. Native test_hle_stats.py and test_cpu_report.py both pass (2 check groups, 0 failures, 0 skips). An additional tiny authored crit.py input confirms that baseline loses an outlined HLE body label while this head restores it and matches the imp-entry reference. Existing Windows profiler/parser checks pass; their Linux ELF execution case skips on this host. The isolated review worktree is clean.

This approval is based on that source and focused native evidence. I did not independently repeat the game measurements, off/on overhead comparison, full suite, Linux link/game run, TSAN or production reporter-thread behavior. The per-call estimates remain fixture-covered as described in the PR; the Linux game request T-DWGM remains outstanding. No game data or build artifacts were transferred.

Independent Windows code/test review of 055a8fac6336d604a655fde58f64f7a47d1d07de: no blocking findings. Reviewed the disabled HLE-entry path, counter publication/bounds/wrap, report-thread start failure, NVN dispatch counting and complete clock-window joins in cpu_report. Native test_hle_stats.py and test_cpu_report.py both pass (2 check groups, 0 failures, 0 skips). An additional tiny authored crit.py input confirms that baseline loses an outlined HLE body label while this head restores it and matches the imp-entry reference. Existing Windows profiler/parser checks pass; their Linux ELF execution case skips on this host. The isolated review worktree is clean. This approval is based on that source and focused native evidence. I did not independently repeat the game measurements, off/on overhead comparison, full suite, Linux link/game run, TSAN or production reporter-thread behavior. The per-call estimates remain fixture-covered as described in the PR; the Linux game request T-DWGM remains outstanding. No game data or build artifacts were transferred.
HumanBean deleted branch feat/hle-call-counters 2026-11-14 20:47:04 +00:00
Some checks are pending
CI / Conventional Commit title (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Blocked by required conditions
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Blocked by required conditions
CI / Workflow lint (actionlint) (pull_request) Blocked by required conditions
Third-party parts / As their notes say (pull_request) Blocked by required conditions
Third-party parts / The same as upstream (pull_request) Blocked by required conditions
Website / Website on Cloudflare (pull_request) Blocked by required conditions
PR description / Description follows the template (pull_request_target) Successful in 5s
Website / Website on Cloudflare (pull_request_target) Has been skipped
Some workflows are waiting to be reviewed.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
MagicBeanDev/Longshot!153
No description provided.