neoclide / coc.nvim

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

Show completions asynchronously to not block typing #456

Closed purpleP closed 5 years ago

purpleP commented 5 years ago
## versions

vim version: NVIM v0.3.2
node version: v8.9.0
coc.nvim version: 0.0.55
term: xterm-256color
platform: linux

## Error messages

## Output channel: java
[Info  - 13:06:59] JDT Language Server started
[object Object]

If language server takes time to show completions it blocks typing.

chemzqm commented 5 years ago

It's not, unless your vim is broken or you're slow vim source.

purpleP commented 5 years ago

@chemzqm I don't think my vim is broken, I haven't recompiled it. What I've done is updated your plugin and that's it. I use coc-java, I don't know why it's slow, but I know one thing for sure. No plugin should do blocking operations on text insert. Which is seems to be the case with your plugin.

Why can't you subscribe to InsertCharPre then create a future with completions response from language server and when it's done show menu if response is still valid (meaning user haven't typed any more letters. Because It seems in practice every language server can be slow sometimes especially on large codebases. You can't just assume that LS will always respond fast enough.

chemzqm commented 5 years ago

coc does lightweight operation of InsertCharPre which should takes less than 10ms. You can comment out the line

    autocmd InsertCharPre       * call s:SyncAutocmd('InsertCharPre', v:char)

in plugin/coc.vim to see if there's difference.

There is no block request to language server in coc.nvim during TextChange or InsertCharPre autocmd

chemzqm commented 5 years ago

No plugin should do blocking operations on text insert.

Most plugin have to do block operation on InsertCharPre and coc have to do it synchronize to fix flick pum on neovim.

purpleP commented 5 years ago

@chemzqm I can't reproduce awful performance right now, although the culprit was definitely your plugin, because after removing it the problem was gone and after adding it again it appeared again. But it still blocks my typing sometimes.

What you're saying seems to be inconsistent.

you're slow vim source

So slow language server can prevent me from typing? It implies your plugin is doing some slow operation on InsertCharPre which has to do something with language server, isn't it?

But then you're saying that your plugin doing some work that shouldn't take more than 10ms.

Your plugin also blocks my typing from time to time, presumably because LS is slow with completions sometimes, so I would bet that the operations that you think shouldn't take more than 10ms take more than 10 ms at least some of time. Which means they should be done asynchronously.

purpleP commented 5 years ago

@chemzqm I've made a screencast in case you don't believe me.

https://asciinema.org/a/gFdxyNTENtJ3Ioq0uSuQqOSvY

Notice how Application.class appears after the delay. It's because I've typed it, but your plugin blocked the input. If LS wouldn't be started at this point it wouldn't block. Which implies that the culprit is synchronous request to LS somewhere.

purpleP commented 5 years ago

@chemzqm Okay, this was very tiring, but I've found that depending on a combination of commented out autocmd the lag goes away and what's the same no matter which autocmd I disable is that as soon as I see completions from language server I see lag in typing. But if completions come from buffer source there's no problem.

So maybe not on InsertCharPre but somewhere else you're doing something that blocks UI. Maybe updating error highlighting or filtering completions, maybe something else I don't know. But it depends on completion source for sure.

I'm glad to help debug this performance issue, maybe we can use logs to see what's taking so long?

chemzqm commented 5 years ago

Please create a minimal vimrc that could reproduce the problem.

chemzqm commented 5 years ago

Also checkout https://github.com/neoclide/coc.nvim/wiki/F.A.Q#my-vim-is-blocked-sometimes

purpleP commented 5 years ago

@chemzqm Thanks, I've tried set hidden doesn't seems to affect anything.

This seems to be minimal config to reproduce.

nvim -u NONE --cmd 'packadd coc.nvim' --cmd 'so ~/.config/nvim/after/plugin/coc.nvim.vim' --cmd 'filetype plugin indent on' --cmd 'syntax enable'

# coc.nvim.vim
fu! s:SetupMappings()
    augroup ClosePopup
        au! CompleteDone * if pumvisible() == 0 | pclose | endif
    augroup END
    inoremap <buffer> <expr> <CR> pumvisible() ? "\<C-y>" : "\<CR>"
    nmap <buffer> <silent> gd <Plug>(coc-definition)
    nmap <buffer> <silent> gy <Plug>(coc-type-definition)
    nmap <buffer> <silent> gi <Plug>(coc-implementation)
    nmap <buffer> <silent> gr <Plug>(coc-references)
    nmap <buffer> <Leader>a <Plug>(coc-codeaction)
    setlocal formatexpr=CocAction('formatSelected')
    nmap <buffer> <silent> <Leader>r <Plug>(coc-rename)
    nnoremap <buffer> <silent> K :call CocAction('doHover')<CR>
    vmap <Leader>a <Plug>(coc-codeaction-selected)
    nmap <Leader>a <Plug>(coc-codeaction-selected)
endfu

augroup SetupCocMappings
    au!
    au FileType c call <SID>SetupMappings()
    au FileType cpp call <SID>SetupMappings()
    au FileType haskell call <SID>SetupMappings()
    au FileType java call <SID>SetupMappings()
    au FileType javascript call <SID>SetupMappings()
    au FileType json call <SID>SetupMappings()
    au FileType python call <SID>SetupMappings()
    au FileType typescript call <SID>SetupMappings()
    au CursorHoldI,CursorMovedI * silent! call CocAction('showSignatureHelp')
    au User CocJumpPlaceholder call CocActionAsync('showSignatureHelp')
augroup END
set hidden

And I'm observing the same behaviour. If I don't see autcomplete items from language server everything works without any noticable delay. But as soon as I see completions from java language server I see lags.

chemzqm commented 5 years ago
au CursorHoldI,CursorMovedI * silent! call CocAction('showSignatureHelp')

You should not use CocAction with your CursorHoldI or CursorMovedI, use CocActionAsync instead, it's documented in readme, coc.txt and https://github.com/neoclide/coc.nvim/wiki/F.A.Q.

chemzqm commented 5 years ago

Maybe I should add a check for it.

purpleP commented 5 years ago

@chemzqm Thanks, changing CocAction to CocActionAsync seems to resolve my issue. I can be mistaken, but I think that it was documented previously that one need to use CocAction specifically show showSignatureHelp. That's why I used it. It just never created any problems until now.

adrigzr commented 5 years ago

Hi @chemzqm,

I have same issue as @purpleP on vim but w/o any custom setup code. For me, changing:

autocmd InsertCharPre       * call s:SyncAutocmd('InsertCharPre', v:char)

with:

autocmd InsertCharPre       * call s:Autocmd('InsertCharPre', v:char)

seems to fix it with no additional issue. No flicking or anything. Maybe it can be changed on vim and remain as sync on neovim?

SOF3 commented 2 years ago

It seems CocAction('doHover') also blocks the UI.

chemzqm commented 2 years ago

@SOF3 please read help :h CocAction()