Skip to content

perf(highlighter): Cache decoration-provider hot paths#1148

Open
seflue wants to merge 3 commits into
nvim-orgmode:masterfrom
seflue:fix/recompute-folds
Open

perf(highlighter): Cache decoration-provider hot paths#1148
seflue wants to merge 3 commits into
nvim-orgmode:masterfrom
seflue:fix/recompute-folds

Conversation

@seflue
Copy link
Copy Markdown
Contributor

@seflue seflue commented May 16, 2026

Typing in folded org-files is slow because nvim_set_decoration_provider's on_line does per-line work on every redraw.

Two commits add caching to foldtext: move vim.fn.foldclosed and vim.fn.col from on_line to on_win, and replace the changedtick wholesale-drop with an nvim_buf_attach listener that keeps the cache consistent under edits.

A third commit applies the same pattern to stars. Each buffer keeps a per-line cache of the (stars) node's end_col; on_bytes shifts and drops entries to stay consistent with edits, and on_changedtree re-queries the changed ranges after a reparse. Edits inside a headline that don't touch the leading stars keep their cache entry, since the stars themselves don't change.

I used the snacks profiler to identify the hot methods; it's not a controlled benchmark, but foldtext.on_line and stars.on_line no longer show up near the top after these changes.

seflue added 2 commits May 15, 2026 16:23
In large folded org-files, foldtext.on_line is a hot
path: two vim.fn calls (foldclosed, col) run per
visible line per redraw, even on cache hits.

Move them into on_win, building a per-window map of
fold boundaries and line lengths for the visible range.
on_line becomes an O(1) lookup. nvim_buf_get_lines
replaces per-line col() queries; foldclosedend lets the
scan skip over folded contents.
Replace the changedtick check that dropped the entire
foldtext cache on every keystroke with an
nvim_buf_attach listener: on_bytes drops cache entries
inside the edited range and shifts later entries by the
row delta, on_reload clears the cache for full reloads.
Unedited closed folds keep their cached hl_group and
skip the treesitter lookup on subsequent redraws.
@kristijanhusak
Copy link
Copy Markdown
Member

I just pushed a change to master to hide leading stars via tree-sitter queries (5ea6251), so we can rebase and simplify this a bit more.

The on_line hook ran a tree query per visible line per redraw,
making leading-star highlighting a hot path while typing.

Cache end_col per buffer line. Shift/drop entries on buffer
edits via nvim_buf_attach (on_bytes/on_reload), and rebuild
the changed ranges from on_changedtree once the parser has
produced a new tree. on_line is now a plain table lookup.

Mirrors the cache pattern already used by foldtext.
@seflue seflue force-pushed the fix/recompute-folds branch from 921b11d to 48f02ee Compare May 17, 2026 11:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants