neoclide / coc.nvim

Nodejs extension host for vim & neovim, load extensions like VSCode and host language servers.
Other
24.33k stars 956 forks source link

Slow startup when using coc + airline #1827

Closed devjgm closed 4 years ago

devjgm commented 4 years ago

UPDATE: I updated to the latest neovim, v0.4.3, and the problem persists. New info in the comment below.

Result from CocInfo

## versions

vim version: NVIM v0.3.4
node version: v10.15.2
coc.nvim version: 0.0.78-bcb2fe977c
term: xterm
platform: linux

Describe the bug

There's a noticeable startup lag when opening a files with neofim + coc + airline. If I comment out either the coc plugin or the airline plugin, nvim starts up quickly with either one. However, when they are both loaded, there's a noticeable lag when first rendering the screen.

Reproduce the bug

We will close your issue when you don't provide minimal vimrc and we can't reproduce it

profile start profile.log
profile func *
profile file *
call plug#begin(stdpath('data') . '/plugged')
Plug 'vim-airline/vim-airline'
Plug 'neoclide/coc.nvim', {'branch': 'release'}
call plug#end()

Make sure plugins are installed with :PlugInstall

There's nothing to do here. The performance lag is just opening nvim and waiting for the screen to draw.

Output from my profile.log

I don't know what <SNR>16_request() does, but it looks like maybe that's suggestive of the problem.

...
FUNCTION  <SNR>16_request()
Called 3 times
Total time:   0.605219
 Self time:   0.605019

count  total (s)   self (s)
    3   0.000116   0.000068   let channel = coc#client#get_channel(self)
    3              0.000030   if empty(channel) | return '' | endif
    3              0.000012   try
    3              0.000010     if s:is_vim
                                  let res = ch_evalexpr(channel, [a:method, a:args], {'timeout': 60 * 1000})
                                  if type(res) == 1 && res ==# ''
                                    throw 'request '.a:method. ' '.string(a:args).' timeout after 60s'
                                  endif
                                  let [l:errmsg, res] =  res
                                  if !empty(l:errmsg)
                                    throw l:errmsg
                                  else
                                    return res
                                  endif
                                else
    3   0.604691   0.604538       return call('rpcrequest', [channel, a:method] + a:args)
                                endif
                              catch /.*/
                                if v:exception =~# 'E475'
                                  if get(g:, 'coc_vim_leaving', 0) | return | endif
                                  echohl Error | echom '['.self.name.'] server connection lost' | echohl None
                                  let name = self.name
                                  call s:on_exit(name, 0)
                                  execute 'silent do User ConnectionLost'.toupper(name[0]).name[1:]
                                elseif v:exception =~# 'E12'
                                  " neovim's bug, ignore it
                                else
                                  echohl Error | echo 'Error on request ('.a:method.'): '.v:exception | echohl None
                                endif
                              endtry
...

FUNCTIONS SORTED ON SELF TIME
count  total (s)   self (s)  function
    3   0.605219   0.605019  <SNR>16_request()
  218   0.021931   0.010474  airline#highlighter#get_highlight()
    2   0.032725   0.010130  <SNR>9_init()
  436              0.009780  <SNR>36_get_syn()
  138   0.030876   0.007830  airline#highlighter#exec()
    4   0.037661   0.006919  airline#highlighter#highlight()
   71              0.005316  <SNR>36_GetHiCmd()
    1   0.006847   0.004474  airline#extensions#load()
   24   0.027309   0.003199  airline#check_mode()
   24   0.003139   0.002538  airline#extensions#whitespace#check()
    1              0.002411  <SNR>13_AddAnsiGroups()
   10   0.003127   0.002362  <SNR>35_create()
  138              0.001936  <SNR>36_CheckDefined()
  218              0.001677  <SNR>36_get_array()
    1              0.001674  <SNR>16_start()
    2   0.012383   0.001575  12()
  184              0.001422  airline#util#winwidth()
   24   0.562112   0.001324  airline#extensions#hunks#get_hunks()
  168              0.001315  airline#util#append()
    3   0.002940   0.001192  airline#init#bootstrap()
fannheyward commented 4 years ago

Upgrade your neovim to latest version and try again.

devjgm commented 4 years ago

OK. I updated to the latest, neovim v0.4.3. The problem persists. Here's the latest info:

CocInfo

## versions

vim version: NVIM v0.4.3
node version: v10.15.2
coc.nvim version: 0.0.78-bcb2fe977c
term: xterm
platform: linux

Snippets from profile.log

...
FUNCTION  <SNR>16_request()
    Defined: ~/.local/share/nvim/plugged/coc.nvim/autoload/coc/client.vim line 122
Called 3 times
Total time:   0.535039
 Self time:   0.534971

count  total (s)   self (s)
    3   0.000083   0.000049   let channel = coc#client#get_channel(self)
    3              0.000019   if empty(channel) | return '' | endif
    3              0.000006   try
    3              0.000006     if s:is_vim
                                  let res = ch_evalexpr(channel, [a:method, a:args], {'timeout': 60 * 1000})
                                  if type(res) == 1 && res ==# ''
                                    throw 'request '.a:method. ' '.string(a:args).' timeout after 60s'
                                  endif
                                  let [l:errmsg, res] =  res
                                  if !empty(l:errmsg)
                                    throw l:errmsg
                                  else
                                    return res
                                  endif
    3              0.000004     else
    3   0.534645   0.534611       return call('rpcrequest', [channel, a:method] + a:args)
                                endif
                              catch /.*/
                                if v:exception =~# 'E475'
                                  if get(g:, 'coc_vim_leaving', 0) | return | endif
                                  echohl Error | echom '['.self.name.'] server connection lost' | echohl None
                                  let name = self.name
                                  call s:on_exit(name, 0)
                                  execute 'silent do User ConnectionLost'.toupper(name[0]).name[1:]
                                elseif v:exception =~# 'E12'
                                  " neovim's bug, ignore it
                                else
                                  echohl Error | echo 'Error on request ('.a:method.'): '.v:exception | echohl None
                                endif
    3              0.000007   endtry

...
FUNCTIONS SORTED ON SELF TIME
count  total (s)   self (s)  function
    3   0.535039   0.534971  <SNR>16_request()
  218   0.032065   0.015951  airline#highlighter#get_highlight()
  436              0.013826  <SNR>37_get_syn()
  138   0.046233   0.012812  airline#highlighter#exec()
    2   0.036125   0.011314  <SNR>9_init()
    4   0.061315   0.010266  airline#highlighter#highlight()
   71              0.007114  <SNR>37_GetHiCmd()
    1   0.007380   0.004790  airline#extensions#load()
   23   0.048596   0.002960  airline#check_mode()
  138              0.002913  <SNR>37_CheckDefined()
   10   0.003696   0.002818  <SNR>36_create()
   23   0.003254   0.002583  airline#extensions#whitespace#check()
  218              0.002288  <SNR>37_get_array()
    1              0.002147  <SNR>13_AddAnsiGroups()
  161              0.001522  airline#util#append()
   23   0.509760   0.001514  airline#extensions#hunks#get_hunks()
   28   0.017747   0.001514  <SNR>37_exec_separator()
  177              0.001434  airline#util#winwidth()
   69   0.001865   0.001260  airline#util#shorten()
    2   0.010302   0.001243  12()
devjgm commented 4 years ago

Also, here's the output of nvim --startuptime. The bottom of the file shows 531ms on "first screen update".

times in msec
 clock   self+sourced   self:  sourced script
 clock   elapsed:              other lines

000.032  000.032: --- NVIM STARTING ---
001.151  001.120: locale set
002.211  001.059: inits 1
002.254  000.043: window checked
002.263  000.010: parsing arguments
002.652  000.389: expanding arguments
002.804  000.151: inits 2
005.193  002.389: init highlight
005.298  000.106: waiting for UI
009.813  004.514: done waiting for UI
009.979  000.167: initialized screen early for UI
016.307  005.793  005.793: sourcing /home/jgm/.local/share/nvim/site/autoload/plug.vim
043.513  024.020  024.020: sourcing /home/jgm/nvim-linux64/share/nvim/runtime/filetype.vim
044.025  000.142  000.142: sourcing /home/jgm/nvim-linux64/share/nvim/runtime/ftplugin.vim
044.314  000.079  000.079: sourcing /home/jgm/nvim-linux64/share/nvim/runtime/indent.vim
045.408  000.583  000.583: sourcing /home/jgm/nvim-linux64/share/nvim/runtime/syntax/syncolor.vim
045.723  001.076  000.493: sourcing /home/jgm/nvim-linux64/share/nvim/runtime/syntax/synload.vim
045.788  001.334  000.258: sourcing /home/jgm/nvim-linux64/share/nvim/runtime/syntax/syntax.vim
045.816  035.538  004.170: sourcing /home/jgm/.config/nvim/init.vim
045.822  000.305: sourcing vimrc file(s)
046.891  000.189  000.189: sourcing /home/jgm/.local/share/nvim/plugged/vim-airline/autoload/airline/init.vim
047.785  000.230  000.230: sourcing /home/jgm/.local/share/nvim/plugged/vim-airline/autoload/airline/parts.vim
050.902  000.381  000.381: sourcing /home/jgm/.local/share/nvim/plugged/vim-airline/autoload/airline/util.vim
051.149  004.934  004.135: sourcing /home/jgm/.local/share/nvim/plugged/vim-airline/plugin/airline.vim
051.820  000.197  000.197: sourcing /home/jgm/.local/share/nvim/plugged/coc.nvim/autoload/coc/rpc.vim
052.660  000.737  000.737: sourcing /home/jgm/.local/share/nvim/plugged/coc.nvim/autoload/coc/util.vim
053.162  000.230  000.230: sourcing /home/jgm/.local/share/nvim/plugged/coc.nvim/autoload/coc/client.vim
057.513  006.090  004.926: sourcing /home/jgm/.local/share/nvim/plugged/coc.nvim/plugin/coc.vim
058.387  000.368  000.368: sourcing /home/jgm/nvim-linux64/share/nvim/runtime/plugin/gzip.vim
058.453  000.019  000.019: sourcing /home/jgm/nvim-linux64/share/nvim/runtime/plugin/health.vim
058.600  000.108  000.108: sourcing /home/jgm/nvim-linux64/share/nvim/runtime/plugin/man.vim
059.324  000.288  000.288: sourcing /home/jgm/nvim-linux64/share/nvim/runtime/pack/dist/opt/matchit/plugin/matchit.vim
059.379  000.729  000.441: sourcing /home/jgm/nvim-linux64/share/nvim/runtime/plugin/matchit.vim
059.620  000.201  000.201: sourcing /home/jgm/nvim-linux64/share/nvim/runtime/plugin/matchparen.vim
060.245  000.580  000.580: sourcing /home/jgm/nvim-linux64/share/nvim/runtime/plugin/netrwPlugin.vim
060.497  000.188  000.188: sourcing /home/jgm/nvim-linux64/share/nvim/runtime/plugin/rplugin.vim
060.685  000.140  000.140: sourcing /home/jgm/nvim-linux64/share/nvim/runtime/plugin/shada.vim
060.766  000.036  000.036: sourcing /home/jgm/nvim-linux64/share/nvim/runtime/plugin/spellfile.vim
060.991  000.183  000.183: sourcing /home/jgm/nvim-linux64/share/nvim/runtime/plugin/tarPlugin.vim
061.146  000.109  000.109: sourcing /home/jgm/nvim-linux64/share/nvim/runtime/plugin/tohtml.vim
061.216  000.029  000.029: sourcing /home/jgm/nvim-linux64/share/nvim/runtime/plugin/tutor.vim
061.464  000.209  000.209: sourcing /home/jgm/nvim-linux64/share/nvim/runtime/plugin/zipPlugin.vim
061.472  001.726: loading plugins
061.565  000.093: loading packages
061.619  000.054: loading after plugins
061.635  000.016: inits 3
062.770  001.135: reading ShaDa
063.441  000.301  000.301: sourcing /home/jgm/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions.vim
063.618  000.077  000.077: sourcing /home/jgm/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions/quickfix.vim
063.874  000.180  000.180: sourcing /home/jgm/.local/share/nvim/plugged/vim-airline/autoload/airline.vim
064.048  000.040  000.040: sourcing /home/jgm/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions/netrw.vim
064.375  000.071  000.071: sourcing /home/jgm/.local/share/nvim/plugged/vim-airline/autoload/airline/section.vim
064.730  000.202  000.202: sourcing /home/jgm/.local/share/nvim/plugged/vim-airline/autoload/airline/highlighter.vim
064.913  000.735  000.462: sourcing /home/jgm/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions/term.vim
065.187  000.105  000.105: sourcing /home/jgm/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions/hunks.vim
065.500  000.054  000.054: sourcing /home/jgm/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions/coc.vim
065.768  000.125  000.125: sourcing /home/jgm/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions/whitespace.vim
066.137  000.093  000.093: sourcing /home/jgm/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions/wordcount.vim
066.324  000.031  000.031: sourcing /home/jgm/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions/keymap.vim
072.874  000.054  000.054: sourcing /home/jgm/.local/share/nvim/plugged/vim-airline/autoload/airline/themes.vim
073.213  000.491  000.437: sourcing /home/jgm/.local/share/nvim/plugged/vim-airline/autoload/airline/themes/dark.vim
088.748  000.123  000.123: sourcing /home/jgm/.local/share/nvim/plugged/vim-airline/autoload/airline/builder.vim
089.062  000.068  000.068: sourcing /home/jgm/.local/share/nvim/plugged/vim-airline/autoload/airline/extensions/default.vim
099.075  033.883: opening buffers
099.096  000.021: BufEnter autocommands
099.099  000.003: editing files in windows
099.264  000.165: VimEnter autocommands
099.266  000.002: UIEnter autocommands
099.267  000.001: before starting main loop
630.977  531.709: first screen update
630.984  000.008: --- NVIM STARTED ---
chemzqm commented 4 years ago

We need debug log of coc.nvim to address this issue, please follow these steps:

It should not use request at all.

chemzqm commented 4 years ago

It's problem of CocAction at https://github.com/vim-airline/vim-airline/blob/master/autoload/airline/extensions/hunks.vim#L25, it could be slow on startup. Remove that code or request for an option to disable detect.

oblitum commented 4 years ago

I recommend lightline (or something lighter or your own statusline). I've hit many of such issues with airline in the past, unrelated to coc.nvim. Was the reason I've stopped using it.

devjgm commented 4 years ago

@chemzqm thank you. I think you identified the problem correctly. Indeed, if I let g:airline#extensions#hunks#enabled = 0 then the problem goes away. I'll do this for now.

@oblitum thanks for the lightline suggestion. I do like lightline. But the thing that keeps me with airline is the nice looking tabline across the top that shows buffers rather than tabs. I know there are ways to make that work with lightline, and maybe I'll do that if airline continues to cause problems.

chrisbra commented 4 years ago

It's problem of CocAction at https://github.com/vim-airline/vim-airline/blob/master/autoload/airline/extensions/hunks.vim#L25, it could be slow on startup. Remove that code or request for an option to disable detect.

that is funny that you mention this here but not to me, when I asked about it https://github.com/neoclide/coc-git/issues/96

Also you did not come back to me with the issues I had about it, simply closed it...

chemzqm commented 4 years ago

@chrisbra I've answered your question before close the issue. One possible solution is use CocActionAsync or check if the extension exists before VimEnter, it's expected to be slow since coc.nvim load all extensions in asynchronous manner.

chrisbra commented 4 years ago

You did not come back to why it did not work. Anyhhow, what exactly do you mean by:

CocActionAsync or check if the extension exists before VimEnter

Or asked the other way around, what would be the best way to ask from another vimplugin to check for coc-git extension being loaded.

chemzqm commented 4 years ago

what would be the best way to ask from another vimplugin to check for coc-git extension being loaded.

My preferred way is not ask at all, provide an option then use g:coc_git_status if user change the option to true, the variable could never exists when user change git.enableGlobalStatus configuration to false

oblitum commented 4 years ago

that is funny that you mention this here but not to me, when I asked about it neoclide/coc-git#96

The knowledge of CocAction vs CocActionAsync is pretty widespread here, to the point when someone refers to one, it's simply assumed that a whole exposition of the two isn't necessary. If you need things async, then just use async version.

Aside that, "air"line started being as a light alternative to powerline but simply lost its way with myriad integrations which are not fully tested. Also as usual, same bad tone when dealing with problems.

chrisbra commented 4 years ago

The knowledge of CocAction vs CocActionAsync is pretty widespread here, to the point when someone refers to one, it's simply assumed that a whole exposition of the two isn't necessary. If you need things async, then just use async version.

While that might be true, it is pretty obvious I am not using coc. And trying to dive into the asycs of another vim plugin might be a bit much asked for.

Aside that, "air"line started being as a light alternative to powerline but simply lost its way with myriad integrations which are not fully tested.

If you have improvements for better integrations, I am all ears. I have never anything against concrete suggestions.

Also as usual, same bad tone when dealing with problems.

You mean from your side, as usual? Talk for yourself please. I am trying to be helpful. Thanks for understanding.

chrisbra commented 4 years ago

My preferred way is not ask at all, provide an option then use g:coc_git_status if user change the option to true, the variable could never exists when user change git.enableGlobalStatus configuration to false

My preferred way would be to use whatever is available, without having the user asked and configured something, that can be configured automatically. After all, that's what computer are good for.

devjgm commented 4 years ago

homer

oblitum commented 4 years ago

You mean from your side, as usual? Talk for yourself please. I am trying to be helpful. Thanks for understanding.

No, I mean "that is funny that you mention this here but not to me, when I asked about it neoclide/coc-git#96". It isn't polite. And you started with sarcasm.

My last message on this off-topic.

chrisbra commented 4 years ago

Look, I asked explicitly how to check for the availability of the coc-git extension from another plugin, because that's what has been asked for in vim-airline. There was no mentioning that this could be slow. How should I know that this is known to be slow when providing this feature? Then mentioning it here in just another issue, where I do not notice it is not helpful. Just ping me if you know this is to be slow or notice it here. I am pretty reactive and even notice if you ping me in other issues.

And you started with sarcasm.

Yes, I asked politely for how to check it. At the very least, one could mention it. Is this asked too much? Yes, I am frustrated, when I notice that issues of vim-airline are being discussed elsewhere where I do not have to a chance to notice and fix it. And yes, this includes your message:

I've hit many of such issues with airline in the past, unrelated to coc.nvim.

as well. If you notice a problem, mention it. I'll try to fix it if it is feasible and I have time and that's how I handle all of my plugin or wherever I take part in a community.

chrisbra commented 4 years ago

@devjgm should be fixed as of https://github.com/vim-airline/vim-airline/commit/48064e24d5d1fd715b2366444a09475bcbe03879

chemzqm commented 4 years ago

My preferred way would be to use whatever is available, without having the user asked and configured something, that can be configured automatically. After all, that's what computer are good for.

The detection can be slow, so an option can be provided to avoid it like what neovim does for g:python_host_prog

chrisbra commented 4 years ago

please correct me if I am wrong, but for once I believe there were also Neovim issues for it being slow and second, since this is async, it may not be available right from the time vim is started and the statusline is drawn the first time.

Anyhow, I have now removed the whole check in airline.

chemzqm commented 4 years ago

CocActionAsync can be used for none block function call to coc.nvim, but that may require lots of change to your codebase.