watchthelight labs

Window drags run at 11-28 flips/s for the first ~3 minutes after login #11

openarea:gpukind:bugseverity:mediumfound-by:featuretest
watchthelight 2026-10-19

Finder window drags right after login run at 11-28 flips/s for about two to three minutes, then settle at 75-77 flips/s. Seen on stock NullMoth 2.3.7 (N-168: 11-26 flips/s from +72 s to +180 s, load 13 falling to 5) and with the fork plugin on 2.3.6 kexts (N-167: 11-28). With the commit-time submit-ahead pass off (N-166) the early runs were 33-39. So part is login load (Spotlight, WindowManager), but the GPU path makes it much worse. Measure: evidence/native/i-069-bisect/timed-drag.sh (waits for the gpu-guard's Good). Next: a WindowServer spindump during a slow early drag. Evidence: project-legion evidence/native/N-167/README.md, evidence/native/N-168/timed-drag-part1.txt. Tracker I-069.

watchthelight 2026-10-23

A lead for the spindump this still needs. On an RTX 2070 Super, nullmoth/nvidia-macos-driver#370 shows WindowServer's coreanimation.pipelines thread in create_fragment_shader for 317 of 353 samples, translating through metal2vulkan, with the shader cache writes (writeToFile, fsync) on the same thread. It was worse on some boots and better after a logout, which looks a lot like our first three minutes after login.

So when we take the WindowServer spindump during a slow early drag, that is the stack to look for, and the second thing to check is whether the translated shader cache survives a reboot. Notes: https://github.com/watchthelight-labs/research/blob/main/scout/nvgfx/2026-10-23.md

watchthelight 2026-10-23

Checked our plugin against that: it does the same thing. nvmtl_translate_with_fc_cached reads, translates and writes the cache file (writeToFile:atomically:, which fsyncs) on whatever thread asked, and the in-memory memo starts empty every time WindowServer starts. So the first minutes after login pay a translate plus an fsync per new shader on WindowServer's own threads.

Branch cache-write-async (2.5.3-nvgfx.2) moves every cache write and last-use touch onto one background queue; reads and the memo stay as they were. NVMTL_CACHE_SYNC_IO=1 in nvrm610.conf puts the old behaviour back for an A/B. The log now also says which cache folder is in use and, after 500 lookups, how many came from memory, from disk, or were translated.

Not built or booted yet. Plan for the next macOS session: a baseline run on 2.5.3-nvgfx.1 with a WindowServer spindump at +75 s (slow phase) and +240 s (fast phase), then the same on this branch. If the spindump shows translations (cache misses) rather than fsyncs, this only helps a little, and the question becomes why the disk cache misses after a reboot.

watchthelight 2026-10-27

Outside measurement: in nullmoth/nvidia-macos-driver#412 someone rebased six of our plugin commits onto 2.6.2 and timed drags on an RTX 5080. Stock 2.6.2 drags at 85 to 100 flips/s with 63 to 124 ms stalls; with our commits the stalls are gone.

One regression came with it: the two commits that cache setRenderPipelineState and the sampler variant made Alacritty (OpenGL) text jump backward, so they held those back. We need to run an OpenGL terminal against those two before closing this.

Write-up: https://github.com/watchthelight-labs/research/blob/main/scout/nvgfx/2026-10-27.md

watchthelight 2026-10-28

The async cache writes from cache-write-async are in the 2.6.2-nvgfx.1 release (CHANGELOG, under 2.5.3-nvgfx.2). On that boot a window drag plus typing in an OpenGL terminal showed no text jumping back, so the Alacritty regression from nullmoth/nvidia-macos-driver#412 did not show up here; NVMTL_NO_PSO_SKIP=1 and NVMTL_NO_SV_MEMO=1 turn those two commits off if it shows up elsewhere. I haven't re-timed the first minutes after login on it yet, so this stays open until that run, with the WindowServer spindump.

Reply on GitHub