Files
benilla-octo/crates/benilla-ui
gromandClaude Opus 5 3e616e5cb3 reload: one VM and no flush storm, 615 ms off every rebuild
Two costs read straight out of the player's own `WOW_UI_HANDLERS=1` session log
(2026-10-18 20:33), where a `/reload` blocks the main thread for 7.84 s.

**The saved-variables flush, 305 ms.** The reload's first act is to write every
loaded addon's saved variables, one file each, and `write_atomic_bytes` ends each
with `sync_all()` — a disk round trip per file, 60 of them, inside the one blocked
frame. Measured on this project's own btrfs home: **327 ms flushed, 6 ms not**,
which is the +27→332 ms the log spends between `ReloadUI — ending the UI session`
and the last `wrote …/saved/*.lua`. `write_atomic_bytes_bulk` keeps the temp file
and the rename (so a file is whole or absent) and gives up only a power loss in
the seconds after; the reference writes these with plain buffered CRT writes and a
`.bak` rotation whose result it discards, so this is still the stronger of the two.

**A whole VM built and thrown away, 310 ms.** `end_ui_session` installs a fresh
boot VM, which is right for the roots that stop there — the character screen runs
on it — but `run_pending_reload` then calls `load_ingame_ui_on_world_entry`, which
mints its own in `mint_entry_vm`. So every reload ran `UiScript::new`,
`GlobalStrings.lua`, the emote table and the font registry twice and let the first
one go without running a line: the log prints `GlobalStrings loaded` at +350 ms and
again at +662 ms. `end_session` now takes what to leave behind, and the reload
leaves the dying VM until the mint replaces it — safe because the two calls are one
exclusive system with nothing in between, the old VM is still dropped before any
file loads, and `fold_dying_vm_cvars` drains what it folds, so the mint's second
fold of the same VM finds nothing. Only when the rebuild is certain to mint: with
no UI wanted (a capture) the load returns early and the world would be left with no
VM at all.

`chunkbench` is the instrument the next item needs, and the one that priced this
one's neighbours: it runs a file list three ways — a VM per file, one VM with the
stock collector, one with it stopped — so parse, execute and the GC's share are
separate numbers. Over his enabled addon set (1,471 files, 70 MiB) the parse is
703 ms against 74 ms to compile the same chunks from bytecode, which is what a
bytecode cache would be worth; the collector is not the problem (829 ms against
731 ms stopped), and pfQuest's 23 database files are 417 ms and 110 MiB of heap.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
2026-10-18 14:59:22 -06:00
..