diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-07-11 08:57:55 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-11 08:57:55 +0800 |
commit | 19fb573ad992b6f658b58159314eeea0c2f30953 (patch) | |
tree | 5d394c657fb5f9d0abe0e1315b54b66914aeefe8 | |
parent | db8fe63a9398efd57c3ff28aa3d93e45fb70ee1a (diff) | |
download | rneovim-19fb573ad992b6f658b58159314eeea0c2f30953.tar.gz rneovim-19fb573ad992b6f658b58159314eeea0c2f30953.tar.bz2 rneovim-19fb573ad992b6f658b58159314eeea0c2f30953.zip |
perf(extmarks): avoid unnecessary marktree traversal with folds (#24306)
Extreme testcase:
```lua
vim.cmd([[
call setline(1, ['', '', ''])
2,3fold
]])
local ns = vim.api.nvim_create_namespace('')
for _ = 1, 100000 do
vim.api.nvim_buf_set_extmark(0, ns, 1, 0, { virt_lines = {{{ '' }}} })
end
local start_time = vim.uv.hrtime()
vim.api.nvim_win_text_height(0, {})
local stop_time = vim.uv.hrtime()
print(stop_time - start_time)
```
Before this PR: 21542011
After this PR: 43874
-rw-r--r-- | src/nvim/decoration.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c index 2027848ccf..59af433b35 100644 --- a/src/nvim/decoration.c +++ b/src/nvim/decoration.c @@ -592,26 +592,34 @@ int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines, TriState has_fo return 0; } - int virt_lines = 0; - int row = MAX(lnum - 2, 0); - int end_row = (int)lnum; - MarkTreeIter itr[1] = { 0 }; - marktree_itr_get(buf->b_marktree, row, 0, itr); + assert(lnum > 0); bool below_fold = lnum > 1 && hasFoldingWin(wp, lnum - 1, NULL, NULL, true, NULL); if (has_fold == kNone) { has_fold = hasFoldingWin(wp, lnum, NULL, NULL, true, NULL); } + + const int row = lnum - 1; + const int start_row = below_fold ? row : MAX(row - 1, 0); + const int end_row = has_fold ? row : row + 1; + if (start_row >= end_row) { + return 0; + } + + int virt_lines = 0; + MarkTreeIter itr[1] = { 0 }; + marktree_itr_get(buf->b_marktree, start_row, 0, itr); while (true) { mtkey_t mark = marktree_itr_current(itr); if (mark.pos.row < 0 || mark.pos.row >= end_row) { break; - } else if (mt_end(mark) || marktree_decor_level(mark) < kDecorLevelVirtLine) { + } else if (mt_end(mark) + || marktree_decor_level(mark) < kDecorLevelVirtLine + || !mark.decor_full) { goto next_mark; } - bool above = mark.pos.row > (lnum - 2); - bool has_fold_cur = above ? has_fold : below_fold; - Decoration *decor = mark.decor_full; - if (!has_fold_cur && decor && decor->virt_lines_above == above) { + Decoration *const decor = mark.decor_full; + const int draw_row = mark.pos.row + (decor->virt_lines_above ? 0 : 1); + if (draw_row == row) { virt_lines += (int)kv_size(decor->virt_lines); if (lines) { kv_splice(*lines, decor->virt_lines); |