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

Neovim performance issues with CursorHold autocmd #100

Closed
antoinemadec opened this issue Jul 2, 2020 · 8 comments
Closed

Neovim performance issues with CursorHold autocmd #100

antoinemadec opened this issue Jul 2, 2020 · 8 comments

Comments

@antoinemadec
Copy link

Explain the issue

neovim CursorHold autocmd is 2x to 5x slower than vim when using vim-matchup

Minimal vimrc file

call plug#begin('~/.vim/plugins')
Plug 'andymass/vim-matchup'
call plug#end()

set nocompatible
set updatetime=100

function s:Start() abort
  let g:start_time = reltimefloat(reltime())
endfunction

function s:End() abort
  let g:end_time = reltimefloat(reltime())
  let g:diff_time = g:end_time - g:start_time
  echom g:diff_time
endfunction

autocmd CursorMoved * call s:Start()
autocmd CursorHold  * call s:End()

let g:matchup_matchparen_deferred = 1

Expected Behavior

diff_time should be 100ms since set updatetime=100.

Actual Behavior

For this example:

  • vim diff_time is constantly around 100ms.
  • neovim diff_time varies a lot from 150ms to more than 200ms on my PC

On my full vimrc:

  • neovim diff_time goes from 150ms to 500ms ❗
  • when disabling vim-matchup, both vim and neovim have the same performance (~100ms)

My config:

  • OS: Debian Testing
  • vim-matchup: up to date
  • nvim:
NVIM v0.5.0-575-g225f0bcd9
Build type: Release
  • vim:
VIM - Vi IMproved 8.2 (2019 Dec 12, compiled May 12 2020 02:37:13)
Included patches: 1-716

Possible Explanations

It might be because:

  1. vim and neovim don't trigger the same code in vim-matchup
  2. some neovim issue/different behavior regarding CursorHold

Regarding 1., I tried to comment out the neovim specific code from vim-matchup and still observed the same slowdown for neovim.
Regarding 2., it might be related to timers, maybe neovim wait for timer to return before executing CursorHold?

What do you think, do you know where the slowdown is coming from?

Also, thank a lot for creating this plugin, it is absolutely amazing ❤️

Thanks,
Antoine

@antoinemadec antoinemadec changed the title Neovim performance with issues autocmd CursorHold Neovim performance issues with CursorHold autocmd Jul 2, 2020
@antoinemadec
Copy link
Author

FYI, this seems to be a neovim issue, I just opened an issue: neovim/neovim#12587

@andymass
Copy link
Owner

andymass commented Jul 2, 2020

Haven't looked into this yet, but could you try increasing or reducing the delay times for deferred highlighting?. It looks like some kind of race condition where if a time event at exactly the same time as cursorhold, you get problems. I know the timer implementation is completely different between nvim and vim.

@antoinemadec
Copy link
Author

antoinemadec commented Jul 2, 2020

@andymass thanks for the quick response.

It is an issue with CursorHold autocmd in neovim.
I created a testcase in neovim/neovim#12587 where the CursorHold never gets executed because it is blocked by timers.
Whereas in vim, CursorHold is not blocked by timers, which seems more reasonnable.

Here are weird observations that I made using the testcase of this issue:

  1. when g:matchup_matchparen_deferred_show_delay=50 update_time=100, slow down: between ~150ms and ~200ms
  2. when g:matchup_matchparen_deferred_show_delay=100 update_time=100, more slow down: between ~200ms and ~300ms
  3. when g:matchup_matchparen_deferred_show_delay=500 update_time=100, almost no slow down: ~100ms most of the time

2- is especially weird since relaxing show_delay should not result in worse performance.

It looks like CursorHold and timers are competing for CPU time in the same thead in neovim.
This results in poorer performance than vim at best, lock conditions in the worst case scenario.

I think vim-matchup does nothing wrong.
We should wait for a response on neovim/neovim#12587

@antoinemadec
Copy link
Author

@andymass , here is a temporary way to fix this perf bug: https://github.com/antoinemadec/FixCursorHold.nvim

@andymass
Copy link
Owner

@antoinemadec interesting, thanks for pointing out this workaround! I wonder if it makes sense to decouple the delay on your plugin from updatetime (which defaults to 4000, and this is how often a swap file is written to disk). My worry is that you will get CursorHold fired twice; once by your plugin and once by neovim.

@antoinemadec
Copy link
Author

antoinemadec commented Jul 15, 2020

@andymass , I used eventignore to avoid firing the CursorHold autocmds twice.
You can take a look at fix_cursorhold_nvim.vim This has been tested, and it works as expected 😃

Regarding the option to decouple CursorHold delay from the updatetime I very much agree with you.
My initial intention was to act like a fixed version of CursorHold in neovim.

This decoupling should ideally come from Vim and Neovim themselves.
There is a note in the :help CursorHold about this:

  		Note: In the future there will probably be
  		another option to set the time.

That being said, I am not against the idea of an option in my plugin that:

  • if defined, used it as CursorHold delay
  • else use updatetime

I am swamped with a bunch of things right now, but I might add it later.
Otherwise, do not hesitate to create a PR.

Cheers!

@antoinemadec
Copy link
Author

@andymass , I just added a separate update time for cursorhold 😃 : antoinemadec/FixCursorHold.nvim@1097c90

@andymass andymass pinned this issue Nov 27, 2020
@andymass
Copy link
Owner

andymass commented Jan 8, 2022

Thanks again for your contribution to users of this plugin @antoinemadec.

The neovim team recently posted a message regarding the buggy nature of CursorHold: https://neovim.discourse.group/t/psa-dont-rely-on-cursorhold-yet/1813. I want to mention that match-up does not use CursorHold in any way, the performance issues were visible when using match-up but not ultimately caused by this plugin. Unfortunately, this still needs to be fixed in neovim and FixCursorHold provides a temporary workaround.

Closing this issue- it remains pinned to help people looking for a solution.

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

No branches or pull requests

2 participants