perf(ui): reuse handles vector in WebGPU custom Dispatch (#132) #148

Merged
catbot merged 1 commit from claude/issue-132 into master 2026-06-18 15:54:36 +02:00
Member

Summary

UIRenderer::Dispatch (implementations/Crafter.Graphics-UI-WebGPU.cpp:180) built a fresh std::vector<uint32_t> handles with reserve on every call, forcing one malloc+free per dispatch. Custom compute dispatches run per-frame, so this is pure per-frame allocation churn.

Fix

Made the vector thread_local and clear() it at the start of each call. Capacity grows to the high-water mark once and is reused thereafter — no allocation after warmup. Chose a reused vector over a fixed std::array because the binding count is a runtime std::vector with no static upper bound, and thread_local keeps it valid even if dispatches ever cross threads. Behavior is byte-for-byte identical.

Testing

crafter-build test — 24 passed. The WebGPU custom-dispatch path itself is browser-only (CRAFTER_GRAPHICS_WINDOW_DOM-guarded) so it isn't exercised by the native suite directly; the change is a behavior-preserving mechanical refactor that compiles clean across the full build.

Resolves #132

## Summary `UIRenderer::Dispatch` (`implementations/Crafter.Graphics-UI-WebGPU.cpp:180`) built a fresh `std::vector<uint32_t> handles` with `reserve` on every call, forcing one malloc+free per dispatch. Custom compute dispatches run per-frame, so this is pure per-frame allocation churn. ## Fix Made the vector `thread_local` and `clear()` it at the start of each call. Capacity grows to the high-water mark once and is reused thereafter — no allocation after warmup. Chose a reused vector over a fixed `std::array` because the binding count is a runtime `std::vector` with no static upper bound, and `thread_local` keeps it valid even if dispatches ever cross threads. Behavior is byte-for-byte identical. ## Testing `crafter-build test` — 24 passed. The WebGPU custom-dispatch path itself is browser-only (`CRAFTER_GRAPHICS_WINDOW_DOM`-guarded) so it isn't exercised by the native suite directly; the change is a behavior-preserving mechanical refactor that compiles clean across the full build. Resolves #132
UIRenderer::Dispatch built a fresh std::vector<uint32_t> with reserve on
every call, paying one malloc+free per dispatch. Custom compute dispatches
run per-frame, so make the vector thread_local and clear() it each call:
capacity grows to the high-water mark once and is reused thereafter,
eliminating the per-frame allocation churn. Behavior is identical.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
catbot merged commit 4c659319cb into master 2026-06-18 15:54:36 +02:00
catbot deleted branch claude/issue-132 2026-06-18 15:54:36 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
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
Catcrafts/Crafter.Graphics!148
No description provided.