Skip to content

refactor(state): Unify window-local state and reuse the cword debounce timer#33

Merged
mhiro2 merged 3 commits into
mainfrom
refactor/unify-window-local-state
Jun 3, 2026
Merged

refactor(state): Unify window-local state and reuse the cword debounce timer#33
mhiro2 merged 3 commits into
mainfrom
refactor/unify-window-local-state

Conversation

@mhiro2

@mhiro2 mhiro2 commented Jun 3, 2026

Copy link
Copy Markdown
Owner

Summary

  • Unify the two divergent window-local state mechanisms onto a single in-memory module store, removing the w:pinwords window-variable round-trips.
  • Centralize per-window cleanup on WinClosed so the in-memory state cannot leak once a window is gone.
  • Reuse one debounce timer per window for cword (guarded against stale fires) instead of churning uv handles on every CursorMoved.
  • Replace non-standard Partial<> annotations with concrete *SetupOpts types and align the standalone runtime slots default (8 -> 9).

Changes

  • 19279eb : refactor(state): unify window-local state into an in-memory store
    • Back the window store with an in-memory module table behind the existing get/set facade, dropping the VimL<->Lua (de)serialization on every access.
    • Add state.clear_win_state to release a window entry explicitly and clear the whole store on teardown.
  • dcb6e0d : refactor(runtime): centralize per-window cleanup and tidy setup typing
    • Funnel WinClosed through one cleanup_window helper that releases cword timers, flash matches and the shared window-store entry.
    • Replace the Partial<> setup annotation with a concrete PinwordsRuntimeSetupOpts.
    • Align the standalone slots default with the real config default (8 -> 9).
  • 35907ab : perf(cword): reuse a single debounce timer per window
    • Reuse one uv timer per window via stop/start instead of close/new on every CursorMoved.
    • Guard the debounce callback with a per-window generation token so a fire scheduled before a restart is dropped rather than updating early or twice.

mhiro2 added 3 commits June 3, 2026 11:34
Per-window match and cword state was kept in the w:pinwords window
variable, incurring VimL<->Lua (de)serialization on every get/set and
diverging from the module-local tables used by the cword runtime and
flash. Back the window store with an in-memory table while keeping the
get/set facade, add clear_win_state to release a window's entry
explicitly, and drop the store on teardown.
WinClosed handling now funnels through a single cleanup_window helper
that releases cword timers, flash matches and the shared window-store
entry, so the in-memory window state no longer leaks once a window is
gone. Replace the non-standard Partial<> annotation on setup with a
concrete PinwordsRuntimeSetupOpts, and align the standalone slots
default with the real config default (8 -> 9).
CursorMoved previously closed and re-created a uv timer on every move,
churning handles throughout the debounce. Reuse one timer per window via
stop/start and guard the callback with a per-window generation token, so
a fire that was already scheduled before a restart is dropped instead of
updating early or twice. Also replace the Partial<> annotation with a
concrete PinwordsCwordRuntimeSetupOpts.
@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown

Benchmark Results

nvim --headless -u NONE -c "lua dofile('bench/run.lua')" -c "qa!"

== bench.bench_reapply ==
---------------------------------------------------------------------------------------------
Benchmark                                        Iters    Mean (us)     Min (us)     Max (us)
---------------------------------------------------------------------------------------------
reapply_all  slots=1 wins=1                         50          1.7          0.1         34.9
reapply_all  slots=1 wins=5                         50          0.8          0.3         12.0
reapply_all  slots=1 wins=10                        50          1.0          0.6         13.9
reapply_all  slots=1 wins=20                        50          1.4          1.2          9.8
reapply_all  slots=5 wins=1                         50          1.5          0.2         30.2
reapply_all  slots=5 wins=5                         50          0.8          0.5          9.4
reapply_all  slots=5 wins=10                        50          1.4          1.1         14.0
reapply_all  slots=5 wins=20                        50          2.3          2.2          2.5
reapply_all  slots=9 wins=1                         50          0.2          0.2          0.4
reapply_all  slots=9 wins=5                         50          0.7          0.7          1.0
reapply_all  slots=9 wins=10                        50          1.4          1.4          1.6
reapply_all  slots=9 wins=20                        50          2.8          2.7          3.1
---------------------------------------------------------------------------------------------

== bench.bench_apply ==
---------------------------------------------------------------------------------------------
Benchmark                                        Iters    Mean (us)     Min (us)     Max (us)
---------------------------------------------------------------------------------------------
apply_slot_globally  wins=1                        100          4.0          2.3         33.4
apply_slot_globally  wins=5                        100         11.2         10.0         23.1
apply_slot_globally  wins=10                       100         21.8         19.0         38.1
apply_slot_globally  wins=20                       100         49.2         40.6         94.5
apply_slot_for_window  existing=0                  200          2.2          2.0         17.2
apply_slot_for_window  existing=5                  200          2.1          1.9         10.8
apply_slot_for_window  existing=9                  200          2.1          2.0         11.9
---------------------------------------------------------------------------------------------

== bench.bench_clear ==
---------------------------------------------------------------------------------------------
Benchmark                                        Iters    Mean (us)     Min (us)     Max (us)
---------------------------------------------------------------------------------------------
clear_all_globally  slots=1 wins=1                  30         75.1         51.6        147.7
clear_all_globally  slots=1 wins=5                  30        121.9         99.2        222.4
clear_all_globally  slots=1 wins=10                 30        200.1        160.1        386.3
clear_all_globally  slots=5 wins=1                  30         67.7         59.9        101.9
clear_all_globally  slots=5 wins=5                  30        189.2        153.8        344.4
clear_all_globally  slots=5 wins=10                 30        304.4        259.5        535.1
clear_all_globally  slots=9 wins=1                  30        108.5         77.3        213.4
clear_all_globally  slots=9 wins=5                  30        248.5        201.5        455.3
clear_all_globally  slots=9 wins=10                 30        401.0        351.2        675.3
---------------------------------------------------------------------------------------------

== bench.bench_set_clear ==
---------------------------------------------------------------------------------------------
Benchmark                                        Iters    Mean (us)     Min (us)     Max (us)
---------------------------------------------------------------------------------------------
set+clear cycle  wins=1                             50         30.6         13.2        149.2
set+clear cycle  wins=5                             50         22.1         19.1         44.0
set+clear cycle  wins=10                            50         41.8         32.0        116.2
---------------------------------------------------------------------------------------------

== bench.bench_jump ==---------------------------------------------------------------------------------------------
Benchmark                                        Iters    Mean (us)     Min (us)     Max (us)
---------------------------------------------------------------------------------------------
jump.next  slots=1                                 100         24.6         13.7         67.2
jump.next  slots=5                                 100       4777.1       4669.7       5481.6
jump.next  slots=9                                 100      14307.8      13962.0      19659.3
---------------------------------------------------------------------------------------------

== bench.bench_cword ==
---------------------------------------------------------------------------------------------
Benchmark                                        Iters    Mean (us)     Min (us)     Max (us)
---------------------------------------------------------------------------------------------
apply_cword_for_window                             200          3.3          2.0         44.1
---------------------------------------------------------------------------------------------

== bench.bench_symbol ==
---------------------------------------------------------------------------------------------
Benchmark                                        Iters    Mean (us)     Min (us)     Max (us)
---------------------------------------------------------------------------------------------
symbol: get_symbol (on identifier)                 200         10.7          3.7         64.9
symbol: get_symbol (on keyword)                    200         12.5          4.3         74.7
symbol: set+clear cycle (source=symbol)             50         23.3         14.5         70.4
symbol: set+clear cycle (source=cword)              50         10.7          9.0         51.8
---------------------------------------------------------------------------------------------

== SUMMARY ==
---------------------------------------------------------------------------------------------
Benchmark                                        Iters    Mean (us)     Min (us)     Max (us)
---------------------------------------------------------------------------------------------
reapply_all  slots=1 wins=1                         50          1.7          0.1         34.9
reapply_all  slots=1 wins=5                         50          0.8          0.3         12.0
reapply_all  slots=1 wins=10                        50          1.0          0.6         13.9
reapply_all  slots=1 wins=20                        50          1.4          1.2          9.8
reapply_all  slots=5 wins=1                         50          1.5          0.2         30.2
reapply_all  slots=5 wins=5                         50          0.8          0.5          9.4
reapply_all  slots=5 wins=10                        50          1.4          1.1         14.0
reapply_all  slots=5 wins=20                        50          2.3          2.2          2.5
reapply_all  slots=9 wins=1                         50          0.2          0.2          0.4
reapply_all  slots=9 wins=5                         50          0.7          0.7          1.0
reapply_all  slots=9 wins=10                        50          1.4          1.4          1.6
reapply_all  slots=9 wins=20                        50          2.8          2.7          3.1
apply_slot_globally  wins=1                        100          4.0          2.3         33.4
apply_slot_globally  wins=5                        100         11.2         10.0         23.1
apply_slot_globally  wins=10                       100         21.8         19.0         38.1
apply_slot_globally  wins=20                       100         49.2         40.6         94.5
apply_slot_for_window  existing=0                  200          2.2          2.0         17.2
apply_slot_for_window  existing=5                  200          2.1          1.9         10.8
apply_slot_for_window  existing=9                  200          2.1          2.0         11.9
clear_all_globally  slots=1 wins=1                  30         75.1         51.6        147.7
clear_all_globally  slots=1 wins=5                  30        121.9         99.2        222.4
clear_all_globally  slots=1 wins=10                 30        200.1        160.1        386.3
clear_all_globally  slots=5 wins=1                  30         67.7         59.9        101.9
clear_all_globally  slots=5 wins=5                  30        189.2        153.8        344.4
clear_all_globally  slots=5 wins=10                 30        304.4        259.5        535.1
clear_all_globally  slots=9 wins=1                  30        108.5         77.3        213.4
clear_all_globally  slots=9 wins=5                  30        248.5        201.5        455.3
clear_all_globally  slots=9 wins=10                 30        401.0        351.2        675.3
set+clear cycle  wins=1                             50         30.6         13.2        149.2
set+clear cycle  wins=5                             50         22.1         19.1         44.0
set+clear cycle  wins=10                            50         41.8         32.0        116.2
jump.next  slots=1                                 100         24.6         13.7         67.2
jump.next  slots=5                                 100       4777.1       4669.7       5481.6
jump.next  slots=9                                 100      14307.8      13962.0      19659.3
apply_cword_for_window                             200          3.3          2.0         44.1
symbol: get_symbol (on identifier)                 200         10.7          3.7         64.9
symbol: get_symbol (on keyword)                    200         12.5          4.3         74.7
symbol: set+clear cycle (source=symbol)             50         23.3         14.5         70.4
symbol: set+clear cycle (source=cword)              50         10.7          9.0         51.8
---------------------------------------------------------------------------------------------

@mhiro2 mhiro2 self-assigned this Jun 3, 2026
@mhiro2 mhiro2 added enhancement New feature or request refactor labels Jun 3, 2026
@mhiro2
mhiro2 merged commit 335ff9c into main Jun 3, 2026
4 checks passed
@mhiro2
mhiro2 deleted the refactor/unify-window-local-state branch June 3, 2026 02:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant