folke / flash.nvim

Navigate your code with search labels, enhanced character motions and Treesitter integration
Apache License 2.0
2.22k stars 27 forks source link

bug: Quite slow on larger files, can this fix it? #331

Open pejrich opened 2 months ago

pejrich commented 2 months ago

Did you check docs and existing issues?

Neovim version (nvim -v)

NVIM v0.9.5 Build type: Release LuaJIT 2.1.1703358377

Operating system/version

macos 14.0

Describe the bug

I have a file that's 133k lines of JSON, about 3mb. Not huge, but bigger than your average code file. This file has a lot of repeated strings, like:

abcde
abcdf
abcdg
...

If I use / to search, flash locks up nvim for a good 5-10 seconds the first few keypresses, and 1-2 seconds after that. I must admit I don't know Nvim or Lua very well, so excuse my ignorance, but I was able to track it down to this line of code

https://github.com/folke/flash.nvim/blob/48817af25f51c0590653bbc290866e4890fe1cbe/lua/flash/labeler.lua#L192

If my understanding of the code is correct, there's a search for each label appended to the current search pattern. I calculated that my file had 36k matches for each of my first two keypresses, and then dropped from there to 5k, 2k, ... I'm not sure if the number of potential matches affects performance, or just the number of labels that are searched.

But after trying a few things, like throttling calls to this function(that didn't work, and caused weird behavior). The following did seem to make things dramatically more responsive, and I couldn't find any bugs, though i've only tested it for a little while:

ok, pos = pcall(vim.fn.searchpos, p, "cnw", 0, 50)

The 50ms timeout I just picked arbitrarily, so maybe there's a better way to pick it, or enable it to be set via config. But was it a deliberate decision to not include a timeout here? Does it cause some side effects that I'm not aware of?

I will continue to run my changes locally to see if anything out of the ordinary happens, but I just wanted to bring it up, as it certainly improved my search speed from 10-15+ seconds of lag, to nearly no lag for this file.

I'm happy to put it in a PR if you think it's a reasonable solution, but I wanted to raise it first in case I'm way off base.

Steps To Reproduce

Get a file and duplicate the word "test" .. i about 50,000 times, so you have test1, test2, etc. . Then do a / search for test999. You'll notice it locks up.

Expected Behavior

Ideally it would be smoother, but I understand that files of this side aren't usually what people are editing.

Repro

-- DO NOT change the paths and don't remove the colorscheme
local root = vim.fn.fnamemodify("./.repro", ":p")

-- set stdpaths to use .repro
for _, name in ipairs({ "config", "data", "state", "cache" }) do
  vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end

-- bootstrap lazy
local lazypath = root .. "/plugins/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", lazypath, })
end
vim.opt.runtimepath:prepend(lazypath)

-- install plugins
local plugins = {
  "folke/tokyonight.nvim",
  { "folke/flash.nvim", opts = {} },
  -- add any other plugins here
}
require("lazy").setup(plugins, {
  root = root .. "/plugins",
})

vim.cmd.colorscheme("tokyonight")
-- add anything else here

EDIT: Also, here's a flame graph if you're interested.

profile