Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(treesitter): rely more on ts correctness #18109

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

vigoux
Copy link
Member

@vigoux vigoux commented Apr 14, 2022

Fixes #18108

@bfredl, this removes an old part of the code that was added a long
time ago.

Now comes the question of actually using ephemeral extmarks, and
rather use persistent extmarks and rely on tree updates.

I just leave that there...

@github-actions github-actions bot added lua stdlib treesitter refactor changes that are not features or bugfixes labels Apr 14, 2022
@github-actions github-actions bot requested a review from bfredl April 14, 2022 12:24
@vigoux vigoux changed the title refactor(ts): rely more on ts correctness refactor(treesitter): rely more on ts correctness Apr 14, 2022
@clason clason added this to the 0.8 milestone Apr 14, 2022
@bfredl
Copy link
Member

bfredl commented Apr 14, 2022

Why remove the state between lines? That seems like a pure regression from a performance perspective (also it just is wrong, we redraw a line range, not a line at a time).

@vigoux
Copy link
Member Author

vigoux commented Apr 14, 2022

Why remove the state between lines? That seems like a pure regression from a performance perspective (also it just is wrong, we redraw a line range, not a line at a time).

Because, as most of my fellow developer, I don't have a terrifically deep understanding of the drawing loop.

Why not sending the end line in the callback to the redrawing ?

@vigoux
Copy link
Member Author

vigoux commented Apr 14, 2022

And what about using static extmarks instead of a complex highlight state ? That will make a huge part of the code simpler to understand.

@bfredl
Copy link
Member

bfredl commented Apr 14, 2022

Because, as most of my fellow developer, I don't have a terrifically deep understanding of the drawing loop.

Any perf related change must be based on "understanding", other wise it is just a random hit or miss. Profiling can help to get empirical understanding (I have used this to get rid of bottlenecks in unexpected places, such as strequal() ).

Why not sending the end line in the callback to the redrawing ?

That's on_win, and could be alternative, but then the hlstate array might get much longer (at the point we could be starting to see O(n^2) behavior there, but likely only for real big windows).

@vigoux
Copy link
Member Author

vigoux commented Apr 14, 2022

Any perf related change must be based on "understanding", other wise it is just a random hit or miss. Profiling can help to get empirical data.

Running the test showed a slight improvement in performances.

If you don't want the changes, just close that PR, I don't care, I just wanted to raise a point (I did twice) about static extmarks, and you plain ignored it twice.

@bfredl
Copy link
Member

bfredl commented Apr 14, 2022

If you don't want the changes, just close that PR, I don't care, I just wanted to raise a point (I did twice) about static extmarks, and you plain ignored it twice.

simply because I needed to think a bit more about that? you posted it 37 minutes ago, and I don't see the hurry, sorry. it could be simpler, though I like the current code that it doesn't duplicate state already in the tree in a second static copy, so I think that is a point for simplicity as well.

@vigoux
Copy link
Member Author

vigoux commented Apr 14, 2022

I think that is a point for simplicity as well.

That is a valid point. Although I think that this is an instance where this simplicity might lead to a bit too much work on the drawing side.

I think we'd need real data in order to compare this in real life. I remember I did a similar change a while back, and that lead to significant performance improvements.

@bfredl
Copy link
Member

bfredl commented Apr 14, 2022

That is a valid point. Although I think that this is an instance where this simplicity might lead to a bit too much work on the drawing side.

Sure but OTOH if you pre-render whenever the tree is changed, you do more work upfront instead (which might not end up being used). I suspect the trade-off varies greatly how much text-editing vs scrolling around the user does.

@vigoux
Copy link
Member Author

vigoux commented Apr 14, 2022

Good point, maybe we need something that redraws the static extmarks in on_win ?

@vigoux
Copy link
Member Author

vigoux commented Apr 15, 2022

@bfredl coming back at this, I am able, with this version of the implementation to limit how far we go on the number of columns.

An even better way of doing this (that I don't know though), would be to pass the very specific byte offsets to the on_line callback, so that we only draw the very portion of the line that the user sees.

@vigoux
Copy link
Member Author

vigoux commented Apr 15, 2022

Thus this version should also fix #14852

@vigoux
Copy link
Member Author

vigoux commented May 2, 2022

Any update on this PR ? I think it is already a step forward in fixing bugs...

@vigoux
Copy link
Member Author

vigoux commented May 3, 2022

I have added the doubling of the match limit value, which should give more room for queries to run.
I think that the PR is ready this way. @bfredl if you want to give a final opinion, I'd be glad to have it.

@vigoux
Copy link
Member Author

vigoux commented May 3, 2022

For the record, this fixes:
nvim-treesitter/nvim-treesitter#1788
nvim-treesitter/nvim-treesitter#1506

@bfredl
Copy link
Member

bfredl commented May 3, 2022

Now that we have untangled the correctness from perf aspect, perhaps we could break out the former to a separate PR? I e more or less the changes to treesitter.c (including the free list, as that is more or less obvious)

@clason
Copy link
Member

clason commented May 3, 2022

That is a good idea, if only because the fix should definitely be backported to 0.7.

@vigoux
Copy link
Member Author

vigoux commented May 3, 2022

I am in favor of this, what parts do you want to separate:

  • free list + synmaxcol
  • iterator reset + doubling?

This way we have the fix on one hand a'd the feature on the other?

@clason
Copy link
Member

clason commented May 3, 2022

I'd say put the kväck and the doubling in a separate fix(treesitter) PR.

@lewis6991
Copy link
Member

lewis6991 commented Jun 16, 2022

For reference, the testcase from lewis6991/gitsigns.nvim#575 is pretty simple:

  1. nvim +'set foldmethod=manual' +'1000,5000fold' +'999' ./src/nvim/eval.c
  2. Move cursor up and down

@vigoux
Copy link
Member Author

vigoux commented Jun 16, 2022

Reproducible, I am going to attempt a little benchmark somehow.

@vigoux
Copy link
Member Author

vigoux commented Jun 16, 2022

I am somehow not able to reproduce this using nvim --clean and that sounds weird to me.

@lewis6991
Copy link
Member

Try making the fold as large as possible.

@vigoux
Copy link
Member Author

vigoux commented Jun 16, 2022

I finally got a benchmark, as follows:

VIMRUNTIME=$(pwd)/runtime/ time nvim --clean -u init.lua ./src/nvim/eval.c
-- init.lua
local parser = vim.treesitter.get_parser(0, "c", {})
local highlighter = vim.treesitter.highlighter.new(parser)

local function keys(keys)
  vim.api.nvim_feedkeys(keys, 't', true)
end

vim.opt.foldmethod = "manual"
vim.opt.lazyredraw = false

vim.cmd [[1000,7000fold]]
vim.cmd [[999]]

local function mk_keys(n)
  local acc = ""
  for i = 1, n do
    acc = acc .. "j"
  end
  for i = 1, n do
    acc = acc .. "k"
  end

  return "qq" .. acc .. "q"
end

keys(mk_keys(10))

for i = 1, 100 do
  keys "@q"
  vim.cmd[[redraw!]]
end

vim.cmd [[quit!]]

With this PR : 0:01.10
Current master: 0:03.11

That's a 3x improvement in performance.

@bfredl
Copy link
Member

bfredl commented Jun 16, 2022

I suppose the presence of a (large) fold could be detected by comparing difference of line param and previous value with some threshold?

@vigoux
Copy link
Member Author

vigoux commented Jun 16, 2022

What's a "large enough" fold ? I think that the data above is a clear indicator of a perf improvement.
I am working on more benchmarks, in order to bring more proofs of the perf improvement.

@bfredl
Copy link
Member

bfredl commented Jun 16, 2022

idk, as a simple starting point we can just do it for any fold (so whenever delta > 1)

@lewis6991
Copy link
Member

lewis6991 commented Jun 16, 2022

Here's my results using the benchmark above.

Time
master 5.168
This PR 1.528
#18760 0.247

So 3x improvement with this PR, but 20x with #18760!!!

So there's some evidence that re-using the iterator is worth doing.

@clason
Copy link
Member

clason commented Jun 16, 2022

We really need a dedicated benchmark test suite (make performancetest), not necessarily for CI, but both for such performance PRs and for regression testing with git bisect.

A PR or dedicated issue for discussing this welcome!

lewis6991 added a commit to lewis6991/neovim that referenced this pull request Jun 16, 2022
@lewis6991
Copy link
Member

Ding #18989

lewis6991 added a commit to lewis6991/neovim that referenced this pull request Jun 16, 2022
lewis6991 added a commit to lewis6991/neovim that referenced this pull request Jun 16, 2022
justinmk pushed a commit that referenced this pull request Jun 17, 2022
@jgarciaokode

This comment was marked as off-topic.

@clason

This comment was marked as off-topic.

kraftwerk28 pushed a commit to kraftwerk28/neovim that referenced this pull request Jul 6, 2022
smjonas pushed a commit to smjonas/neovim that referenced this pull request Dec 31, 2022
@zeertzjq zeertzjq removed the lua stdlib label Mar 22, 2023
@clason clason modified the milestones: 0.9, 0.10 Mar 31, 2023
@dundargoc dundargoc modified the milestones: 0.10, backlog Mar 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
refactor changes that are not features or bugfixes treesitter
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Tree-sitter based highlight may be inefficient
7 participants