andymass / vim-matchup

vim match-up: even better % :facepunch: navigate and highlight matching words :facepunch: modern matchit and matchparen. Supports both vim and neovim + tree-sitter.
https://www.vim.org/scripts/script.php?script_id=5624
MIT License
1.66k stars 65 forks source link

[performance] startuptime is 10ms #146

Open antoinemadec opened 3 years ago

antoinemadec commented 3 years ago

Explain the issue

The startup time of vim-matchup is 10ms:

117.882  011.245  009.383: sourcing /home/antoine/dotfiles/.vim/plugins/vim-matchup/plugin/matchup.vim
  1. What vim version are you using? latest nvim 0.5 dev
  2. Steps to reproduce: nvim --stratuptime profiling.txt ; grep matchup profiling.txt
  3. Expected behavior: faster startuptime, out of the 34 plugins I use this is the 2nd slowest (1st is polyglot)
  4. Observed behavior: slow startuptime

Minimal vimrc file


let &rtp  = '~/.vim/bundle/vim-matchup,' . &rtp
let &rtp .= ',~/.vim/bundle/vim-matchup/after'

Questions

Do you think the init performance could be fixed ? I saw #25 was already talking about this.

Anyway, thanks a lot for the amazing plugin :heart:

andymass commented 3 years ago

Just pushed a change which will hopefully improve it a bit (couple ms at most). PS. you can use :MatchupShowTimes to get a finer idea of where the time is being spent, which might help make further improvements.

antoinemadec commented 3 years ago

@andymass , thanks a lot. I just updated vim-matchup to your latest commit. Here is the before/after, unfortunately there is not much difference:

Before

011.294  009.455: sourcing /home/antoine/dotfiles/.vim/plugins/vim-matchup/plugin/matchup.vim
                                   average       last          maximum
[loader_init_buffer]
  done                             3.13ms        1.74ms        3.44ms
[loading]
  init_done                        8.26ms        8.26ms        8.26ms
[loading_module]
  misc                             0.03ms        0.03ms        0.03ms
  motion                           0.21ms        0.12ms        0.23ms
  loader                           1.08ms        1.08ms        1.08ms
  matchparen                       1.76ms        1.76ms        1.76ms
[matchparen.highlight]
  get_current                      2.00ms        3.88ms        3.88ms
[s:get_delim]
  first_pass                       0.58ms        1.76ms        1.76ms
  nothing_found                    0.65ms        1.96ms        1.96ms

After

011.241  009.357: sourcing /home/antoine/dotfiles/.vim/plugins/vim-matchup/plugin/matchup.vim
                                   average       last          maximum
[loader_init_buffer]
  done                             3.03ms        1.06ms        3.46ms
[loading]
  init_done                        8.17ms        8.17ms        8.17ms
[loading_module]
  misc                             0.03ms        0.03ms        0.03ms
  motion                           0.23ms        0.11ms        0.26ms
  loader                           1.11ms        1.11ms        1.11ms
  matchparen                       1.73ms        1.73ms        1.73ms
[matchparen.highlight]
  get_current                      2.02ms        3.89ms        3.89ms
[s:get_delim]
  first_pass                       0.62ms        1.71ms        1.71ms
  nothing_found                    0.70ms        1.91ms        1.91ms
antoinemadec commented 3 years ago

This takes roughly 3.5ms:

  lua require'treesitter-matchup'.init()

This takes 2.8ms:

  for l:mod in [ 'loader', 'matchparen' ]
    if !get(g:, 'matchup_'.l:mod.'_enabled', 1)
      continue
    endif
    call matchup#{l:mod}#init_module()
  endfor
andymass commented 3 years ago

Thanks, this info helps. BTW, your timings suggest you're opening a file (rather than just opening nvim). Can you share the details of the file you're opening and also any details of your configuration?

antoinemadec commented 3 years ago

@andymass , the second time, I used my regular config and opened my vimrc. The first time, I did not open any file and used the minimal vimrc.

Here are the new stats on the latest vim-matchup, with the minimal vimrc and without opening any file:

022.713  000.343  000.343: sourcing /home/antoine/.vim/plugins/vim-matchup/autoload/matchup.vim
022.914  000.142  000.142: sourcing /home/antoine/.vim/plugins/vim-matchup/autoload/matchup/perf.vim
023.950  000.586  000.586: sourcing /home/antoine/.vim/plugins/vim-matchup/autoload/matchup/loader.vim
025.057  000.912  000.912: sourcing /home/antoine/.vim/plugins/vim-matchup/autoload/matchup/matchparen.vim
030.716  009.253  007.043: sourcing /home/antoine/.vim/plugins/vim-matchup/plugin/matchup.vim
035.255  000.009  000.009: sourcing /home/antoine/.vim/plugins/vim-matchup/after/plugin/matchit.vim
039.434  000.032  000.032: sourcing /home/antoine/.vim/plugins/vim-matchup/autoload/matchup/re.vim
039.734  000.070  000.070: sourcing /home/antoine/.vim/plugins/vim-matchup/autoload/matchup/ts_engine.vim
041.613  000.170  000.170: sourcing /home/antoine/.vim/plugins/vim-matchup/autoload/matchup/pos.vim
024.257  000.430  000.430: sourcing /home/antoine/.vim/plugins/vim-matchup/autoload/matchup.vim
024.483  000.149  000.149: sourcing /home/antoine/.vim/plugins/vim-matchup/autoload/matchup/perf.vim
025.546  000.596  000.596: sourcing /home/antoine/.vim/plugins/vim-matchup/autoload/matchup/loader.vim
026.791  000.929  000.929: sourcing /home/antoine/.vim/plugins/vim-matchup/autoload/matchup/matchparen.vim
031.490  009.005  006.574: sourcing /home/antoine/.vim/plugins/vim-matchup/plugin/matchup.vim
035.520  000.007  000.007: sourcing /home/antoine/.vim/plugins/vim-matchup/after/plugin/matchit.vim
039.756  000.031  000.031: sourcing /home/antoine/.vim/plugins/vim-matchup/autoload/matchup/re.vim
040.059  000.072  000.072: sourcing /home/antoine/.vim/plugins/vim-matchup/autoload/matchup/ts_engine.vim
041.895  000.119  000.119: sourcing /home/antoine/.vim/plugins/vim-matchup/autoload/matchup/pos.vim
                                   average       last          maximum
[loader_init_buffer]
  done                             2.72ms        2.72ms        2.72ms
[loading]
  init_done                        6.96ms        6.96ms        6.96ms
[loading_module]
  misc                             0.02ms        0.02ms        0.02ms
  motion                           0.18ms        0.11ms        0.19ms
  loader                           0.87ms        0.87ms        0.87ms
  matchparen                       1.25ms        1.25ms        1.25ms
krishnakumarg1984 commented 2 years ago

Any further updates/thoughts on the performance? Matchup is slow for me as well and hampers the startup time. Is there any benefit in lazyloading it on the { "%", "g%"} keys using packer's lazy loading feature in neovim?

andymass commented 2 years ago

@krishnakumarg1984 can you give any specific example where it is slow? A lot has been done since this issue opened and it is highly configuration dependent.

I strongly recommend not using packer's lazy loading; a) match-up is already lazy loaded with autoload, b) you would not get matchparen highlighting, c) has not been tested this way and the startup routines in neovim especially involving nvim-treesitter are brittle.

That being said, a specific demonstration will go a long way to finding where the bad performance is.

krishnakumarg1984 commented 2 years ago

Unfortunately, I am unable to share the gist link to the actual document, since we are writing a collaborative report on a jointly funded large-scale research project. The whole doc is a single markdown file jointly edited by about 20 authors (some authors are more active than others e.g. the principal investigator rarely edits the doc).

I find matchup to be slow when editing this very large single-file markdown (actually R markdown document) with lots of embedded code (literate programming style). And since I directly edit nvim my_report.rmd, the load time is pretty unbearable. Note that this report is a monolithic file. It wasn't intended constructed like this in the first place but over the last 18 months or so became like this, and people are now reluctant to modularize it (since we depend on R/pythonvariables defined in the earlier part of the file at some later part of the document), and just want to submit it to the funder and be done. Other people in the project load it up with Rstudio on beefy macs and workstations, which makes the editing somewhat bearable for them, but pretty much everyone is complaining at this point.

matchup is my only vimscript plugin (everything else is a lua plugin), and I was wondering when I saw this issue if the slowdown reported in this issue might be what I am seeing.

andymass commented 2 years ago

Thanks @krishnakumarg1984, from your response, I can infer the following:

  1. The issue is with a non-tree-sitter filetype, specifically rmd. Please let me know what plugin enables the rmd filetype. Or otherwise what nvim configuration you are using to give syntax for this type.

  2. Happens on particularly large files

  3. The issue is specifically with load time, not runtime performance. This does not make sense to me since match-up does almost no work at load time.

Also, if you have not already, please consider setting :let g:matchup_matchparen_deferred=1.

andymass commented 2 years ago

I constructed a 250K line rmd file and loaded it with nvim, match-up takes less than 1 ms to load.

Even if the file cannot be shared, I think some details of your config can help here.