feat(vt): add SafeEmulator.View/Update for batched locked access#887
Open
LXXero wants to merge 1 commit into
Open
feat(vt): add SafeEmulator.View/Update for batched locked access#887LXXero wants to merge 1 commit into
LXXero wants to merge 1 commit into
Conversation
SafeEmulator.CellAt takes an RLock (plus its defer) on every call.
A renderer walking the cell grid each frame pays that per cell —
tens of thousands of lock acquisitions per frame on a large grid.
Profiling a real terminal application (xerotty) under continuous
redraw showed SafeEmulator.CellAt and its defer wrapper as the top
CPU entry (~16% of total) once other per-cell costs were removed.
View(fn) / Update(fn) expose the underlying Emulator under a single
read/write lock acquisition, bbolt-style, so bulk reads (render
passes, snapshots) and bulk writes (cell-by-cell replay) batch into
one lock each:
BenchmarkCellAtGridWalk-16 162933 14081 ns/op
BenchmarkViewGridWalk-16 1885207 1255 ns/op
(80x24 grid walk, 11x. The gap widens with grid size.)
Includes -race tests for both, with concurrent Write pressure.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
SafeEmulator.CellAttakes an RLock (plus its deferred unlock) on every call. Any consumer that walks the cell grid per frame — i.e., every renderer built on vt — pays this per cell: an 80×24 grid is ~2k lock acquisitions per pass, and real applications run multiple passes per frame on much larger grids.Profiling xerotty (a terminal emulator built on vt) under continuous redraw with Linux
perf: after eliminating our own per-cell costs,SafeEmulator.CellAt+ its defer wrapper remained the top CPU entry at ~16% of total process time (~15k lock+defer pairs per frame on a 240×65 grid at 20fps ≈ 300k lock ops/sec, all to read cells that cannot change mid-frame).Change
bbolt-style scoped accessors, purely additive:
Renderers wrap each frame's grid walk in one
View; bulk mutations (e.g. replaying a snapshot via SetCell) batch under oneUpdate. Existing per-call methods unchanged.Benchmark
An 80×24 grid walk, per-cell
CellAtvs the same reads under oneView:11× — and the gap widens with grid size (lock cost is per-cell, savings are per-batch).
Testing
TestSafeEmulatorViewUpdate— basic read/write through the accessorsTestSafeEmulatorViewConcurrent— grid-walking Views against concurrent Write pressure,-racecleanRelated: #879 (same SafeEmulator synchronization layer).