WIP: perf(host): the write marks' collection steps over 256 clear marks at a time #63
No reviewers
Labels
No labels
accessibility
autorelease: pending
autorelease: tagged
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
needs measurements
question
testing wanted
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Longshot!63
Loading…
Reference in a new issue
No description provided.
Delete branch "HumanBean/Longshot:perf/collect-wide"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Why
Every submit collects the pages the game wrote since the last one, on the thread that replays the frame. The walk over the write marks was most of that cost, and almost every mark it looks at is clear. This takes about 0.12-0.24 ms a frame of CPU time off the replay thread in Kokiri Forest; no frame-rate gain is claimed.
What changed
collect_in(host/rx_backend.c) walks one mark byte per 4 KB page over every range the GPU can see. It stepped 32 marks at a time while none was set. It now tests 256 marks at once first (32 words; the compiler makes four AVX2 loads of them), and falls back to the 32 and 8 mark steps where something is marked.HOS_COLLECT_WIDE=0turns the wide step off (for A/B).tests/test_collect_wide.pycompilescollect_infrom the source and compares it with a plain walk over random marks and ranges (aligned or not, short, empty, past the guest's end, past the array's end), with the switch on and off, and checks that the wide step is really taken.Flags and settings
HOS_COLLECT_WIDE0turns the 256-mark step off, leaving the 32 and 8 mark steps as before (for A/B)The switch is not yet in the switch reference of
docs/development.md.Measurements
Baseline: this PR @
20e0b2d9, HOS_COLLECT_WIDE=0main was not the comparison: the switch turns the change off inside the same build, so the two sides differ in nothing else.
main:
15d4ae8c(2026-11-12)this PR: perf/collect-wide @
20e0b2d9Hardware: RTX 3090, NVIDIA 620.70.06, Linux (CPU and RAM not recorded in this description)
Scene: Kokiri Forest, the pristine save, standing; 2048x1152 window, default options, 6 submits a frame
Method: four runs in the order A B B A (A is
HOS_COLLECT_WIDE=0, B the default); the renderer's own line,vk: a submit's memory work (ms): ... writes collected, 600 submits a line, 8 lines a runHow to reproduce: start the game into Kokiri Forest on the pristine save with default options, stand still, and read the
vk: a submit's memory work (ms)lines of the log, once withHOS_COLLECT_WIDE=0and once without itThe timed build was on an older base than the final commit. The game that was timed was built with this change on main
15d4ae8c. The change then moved onto a newer main without conflict as20e0b2d9, and the branch headdc3ae7bamerges the forge's main into it. No game was built or timed on the final tree; the new test compiles the function from the final source.20e0b2d9, HOS_COLLECT_WIDE=020e0b2d9, default (wide step on)That is 0.02-0.04 ms a submit, about 0.12-0.24 ms a frame of CPU time on the replay thread.
No frame-rate gain is claimed. In this scene the frame is bounded by the GPU's time and the present's wait for it, not by this thread's CPU time, so the fps of the runs does not move outside its noise (the four runs, in the order run: 56.6, 68.4, 59.5 and 62.25 fps, on a PC that was swapping throughout; they say nothing either way).
Not measured: the 1% low, the median and p99 frame time, and a run of unchanged main beside the switch. The log lines themselves are not pasted here, only the figures read from them.
Testing
Tested:
tests/test_collect_wide.py(new), on Linux: the function compiled from the source against a plain walk, with the switch on and off.python -I -B tests/run_all.py: 501 passed, 2 failed, 26 skipped on this PC (Linux, 4 at once), the same on the tree merged with the forge's main. The two that fail need tools this PC lacks (zstandard,libtk) and fail on unchanged main here too.Not tested:
Needs other testers:
HOS_COLLECT_WIDE=0(request to open)Screenshots
Nothing on screen.
Risk and rollback
The walk decides which written pages reach the GPU: a mistake in it would show as stale or missing data on screen. The test compares it with a plain walk over random marks and ranges.
HOS_COLLECT_WIDE=0turns the wide step off; reverting the commit is enough to remove it.Reviewer notes
Read
collect_ininhost/rx_backend.cfirst: the 256-mark test is in front of the 32 and 8 mark steps, which are unchanged.Issues
None.
Checklist
For everyone
type(scope): description).main. (Not rebased: the forge's main was merged into the branch, and main has moved on since that merge.)python -I -B tests/run_all.pyrun and passing (any failure that also fails onmainis named above).third_party/untouched (a new folder with aPROVENANCE.mdinstead).If applicable
Assisted-by:/Co-Authored-By:trailers.docs/tested-configurations.mdfor each measured run. (Not added.)MKWVK_API_VERSIONbumped (gpu/vk/vk_api.h'sMkwVkHostorMkwVkRendererchanged). (n/a)mainand passing here. (n/a: not a fix. A game-free test of the new walk is added.)tests/that reads changed source updated in this PR, not weakened. (n/a)The description is now in the template's sections. No code changed and no new numbers: the same facts as before, with the commits the measurements were taken on named, and the checklist ticked only where true. Three For everyone boxes are not true yet (main has moved since the branch merged it; the test requests are not open; the timed build was on an older main, with no median), so this goes back to work in progress.
perf(host): the write marks' collection steps over 256 clear marks at a timeto WIP: perf(host): the write marks' collection steps over 256 clear marks at a timeView command line instructions
Checkout
From your project repository, check out a new branch and test the changes.