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

A large amount of calls to redraw make rendering slow #4681

Open
cheshire opened this issue Jun 21, 2023 · 4 comments
Open

A large amount of calls to redraw make rendering slow #4681

cheshire opened this issue Jun 21, 2023 · 4 comments
Labels
enhancement New feature or request

Comments

@cheshire
Copy link

cheshire commented Jun 21, 2023

On neovim 0.9.1, latest release checkout seems very slow for basic editing with autocompletion, I went back to 69f954e which seems considerably faster.

I have relatively minimal vimrc, using clangd as an LSP.

The only thing which jumps out in the profile after editing for a while is this function:

FUNCTION  coc#pum#create()
    Defined: ~/.local/share/nvim/plugged/coc.nvim/autoload/coc/pum.vim:363
Called 21 times
Total time:   1.249876
 Self time:   1.057834

count  total (s)   self (s)
   21              0.000306   if mode() !=# 'i' || a:opt['line'] != line('.')
                                return
   21              0.000025   endif
   21              0.000137   let len = col('.') - a:opt['col'] - 1
   21              0.000035   if len < 0
                                return
   21              0.000012   endif
   21              0.000165   let input = len == 0 ? '' : strpart(getline('.'), a:opt['col'], len)
   21              0.000054   if input !=# a:opt['input']
    3              0.000002     return
   18              0.000011   endif
   18   0.003133   0.000313   let config = s:get_pum_dimension(a:lines, a:opt['col'], a:config)
   18              0.000035   if empty(config)
                                return
   18              0.000009   endif
   18              0.000089   let s:reversed = get(a:config, 'reverse', 0) && config['row'] < 0
   18              0.000070   let s:virtual_text = s:virtual_text_support && a:opt['virtualText']
   18              0.000049   let s:pum_size = len(a:lines)
   18              0.000039   let s:pum_index = a:opt['index']
   18   0.000395   0.000194   let lnum = s:index_to_lnum(s:pum_index)
   18              0.000394   call extend(config, { 'lines': s:reversed ? reverse(copy(a:lines)) : a:lines, 'relative': 'cursor', 'nopad': 1, 'cursorline': 1, 'index': lnum - 1, 'focusable': v:false })
   18   0.001109   0.000314   call extend(config, coc#dict#pick(a:config, ['highlight', 'rounded', 'highlights', 'winblend', 'shadow', 'border', 'borderhighlight']))
   18              0.000023   if s:reversed
                                for item in config['highlights']
                                  let item['lnum'] = s:pum_size - item['lnum'] - 1
                                endfor
   18              0.000012   endif
   18              0.000101   if empty(get(config, 'winblend', 0)) && exists('&pumblend')
   18              0.000053     let config['winblend'] = &pumblend
   18              0.000012   endif
   18   0.148211   0.000264   let result =  coc#float#create_float_win(s:pum_winid, s:pum_bufnr, config)
   18              0.000033   if empty(result)
                                return
   18              0.000009   endif
   18              0.000031   let s:inserted = 0
   18              0.000060   let s:pum_winid = result[0]
   18              0.000035   let s:pum_bufnr = result[1]
   18              0.000050   let s:start_col = a:opt['startcol']
   18              0.000093   call setwinvar(s:pum_winid, 'above', config['row'] < 0)
   18   0.000253   0.000191   let firstline = s:get_firstline(lnum, s:pum_size, config['height'])
   18              0.000019   if s:is_vim
                                call popup_setoptions(s:pum_winid, { 'firstline': firstline })
   18              0.000013   else
   18   0.001281   0.000170     call coc#compat#execute(s:pum_winid, 'call winrestview({"lnum":'.lnum.',"topline":'.firstline.'})')
   18              0.000010   endif
   18   0.000472   0.000162   call coc#dialog#place_sign(s:pum_bufnr, s:pum_index == -1 ? 0 : lnum)
                              " content before col and content after cursor
   18              0.000056   let linetext = getline('.')
   18              0.000130   let parts = [strpart(linetext, 0, s:start_col), strpart(linetext, col('.') - 1)]
   18              0.000082   let input = strpart(getline('.'), s:start_col, col('.') - 1 - s:start_col)
   18              0.000064   call setwinvar(s:pum_winid, 'input', input)
   18              0.000049   call setwinvar(s:pum_winid, 'parts', parts)
   18              0.000096   call setwinvar(s:pum_winid, 'words', a:opt['words'])
   18              0.000042   call setwinvar(s:pum_winid, 'kind', 'pum')
   18              0.000018   if !s:is_vim
   18              0.000035     if s:pum_size > config['height']
    6              1.052670       redraw
    6   0.032077   0.000161       call coc#float#nvim_scrollbar(s:pum_winid)
   12              0.000008     else
   12   0.001784   0.000109       call coc#float#close_related(s:pum_winid, 'scrollbar')
   18              0.000009     endif
   18              0.000008   endif
   18   0.005384   0.000179   call s:on_pum_change(0)

Not sure if that's helpful, but hopefully it not just me.

@cheshire
Copy link
Author

The overall profile is:

FUNCTIONS SORTED ON TOTAL TIME
count  total (s)   self (s)  function
   21   1.249876   1.057834  coc#pum#create()
    3   0.624954   0.539911  coc#dialog#create_cursor_float()
   23   0.245502   0.059205  coc#float#create_float_win()
   19   0.114232   0.007366  sy#start()
   14   0.087026   0.076544  sy#repo#get_diff()
   23   0.086316   0.000958  <SNR>235_add_highlights()
   23   0.085125   0.028239  coc#highlight#add_highlights()
   65   0.070983   0.047015  coc#util#get_bufoptions()
   23   0.064492   0.002725  coc#float#nvim_create_related()
    5   0.057875   0.050767  coc#float#nvim_right_pad()
   22   0.042941   0.035757  coc#float#nvim_scrollbar()
 1211   0.042624             coc#highlight#add_highlight()
  262   0.027557   0.003581  <SNR>126_Autocmd()
    2   0.027326   0.000346  coc#dialog#create_pum_float()
  291   0.027110   0.005255  coc#rpc#notify()
   13   0.024323   0.023964  <SNR>235_set_float_defaults()
   65   0.023137             coc#util#variables()
  130   0.022989   0.021102  <SNR>197_Highlight_Matching_Pair()
   14   0.022158   0.000223  <SNR>224_callback_nvim_exit()
   14   0.021934   0.003456  <SNR>224_handle_diff()

FUNCTIONS SORTED ON SELF TIME
count  total (s)   self (s)  function
   21   1.249876   1.057834  coc#pum#create()
    3   0.624954   0.539911  coc#dialog#create_cursor_float()
   14   0.087026   0.076544  sy#repo#get_diff()
   23   0.245502   0.059205  coc#float#create_float_win()
    5   0.057875   0.050767  coc#float#nvim_right_pad()
   65   0.070983   0.047015  coc#util#get_bufoptions()
 1211              0.042624  coc#highlight#add_highlight()
   22   0.042941   0.035757  coc#float#nvim_scrollbar()
   23   0.085125   0.028239  coc#highlight#add_highlights()
   13   0.024323   0.023964  <SNR>235_set_float_defaults()
   65              0.023137  coc#util#variables()
  130   0.022989   0.021102  <SNR>197_Highlight_Matching_Pair()
   19              0.019297  <SNR>222_get_path()
  302   0.020374   0.018677  <SNR>128_notify()
  359   0.015148   0.013372  coc#status()
   14   0.015454   0.010154  sy#sign#process_diff()
    5   0.010260   0.008615  coc#util#editor_infos()
    2   0.008361   0.008014  <SNR>220_LogBatchUsingNvimJob()
   19   0.114232   0.007366  sy#start()
   31   0.006910   0.006811  coc#float#create_buf()


@cheshire
Copy link
Author

Seems the slowdown is due to coc.nvim eagerly calling redraw very often? On an older version, I see the same problem when the file has a large number of LSP errors, leading to profiles like

FUNCTION  coc#dialog#create_cursor_float()
    Defined: ~/.local/share/nvim/plugged/coc.nvim/autoload/coc/dialog.vim:69
Called 21 times
Total time:   2.588014
 Self time:   2.552789

count  total (s)   self (s)
   21   0.000154   0.000120   if coc#prompt#activated()
                                return v:null
   21              0.000008   endif
   21              0.000045   let pumAlignTop = get(a:config, 'pumAlignTop', 0)
   21              0.000052   let modes = get(a:config, 'modes', ['n', 'i', 'ic', 's'])
   21              0.000025   let mode = mode()
   21              0.000034   let currbuf = bufnr('%')
   21              0.000039   let pos = [line('.'), col('.')]
   21              0.000037   if index(modes, mode) == -1
   13              0.000008     return v:null
    8              0.000002   endif
    8              0.000047   if !s:is_vim && !has('nvim-0.5.0') && mode ==# 'i'
                                " helps to fix undo issue, don't know why.
                                call feedkeys("\<C-g>u", 'n')
    8              0.000002   endif
    8              0.000015   if mode ==# 's' && has('patch-8.2.4969') && !has('patch-8.2.4996')
                                echohl WarningMsg | echon 'Popup not created to avoid issue #10466 on vim >= 8.2.4969' | echohl None
                                return v:null
    8              0.000002   endif
    8   0.002744   0.000071   let dimension = coc#dialog#get_config_cursor(a:lines, a:config)
    8              0.000008   if empty(dimension)
                                return v:null
    8              0.000002   endif
    8   0.000081   0.000061   if coc#pum#visible() && ((pumAlignTop && dimension['row'] <0)|| (!pumAlignTop && dimension['row'] > 0))
                                return v:null
    8              0.000003   endif
    8              0.000010   let width = dimension['width']
    8   0.000458   0.000294   let lines = map(a:lines, {_, s -> s =~# '^─' ? repeat('─', width) : s})
    8              0.000101   let config = extend(extend({'lines': lines, 'relative': 'cursor'}, a:config), dimension)
    8   0.001814   0.000063   call s:close_auto_hide_wins(a:winid)
    8   0.028252   0.000093   let res = coc#float#create_float_win(a:winid, a:bufnr, config)
    8              0.000008   if empty(res)
                                return v:null
    8              0.000002   endif
    8              0.000014   let alignTop = dimension['row'] < 0
    8              0.000010   let winid = res[0]
    8              0.000006   let bufnr = res[1]
    8              2.551121   redraw
    8              0.000111   if has('nvim')
    8   0.002609   0.000184     call coc#float#nvim_scrollbar(winid)
    8              0.000003   endif
    8              0.000018   return [currbuf, pos, winid, bufnr, alignTop]

Making moving unusably slow. Is there a way to redraw less often?

@cheshire cheshire changed the title Latest release (bbaa1d5d1ff3cbd9d26bb37cfda1a990494c4043) is slow A large amount of calls to redraw make rendering slow Jun 21, 2023
@luisdavim
Copy link

I also notice a slowdown when the language server is reporting errors.

@chemzqm chemzqm added the enhancement New feature or request label Aug 31, 2023
@chemzqm
Copy link
Member

chemzqm commented Aug 31, 2023

Try comment out that redraw command, it's only needed for get correct position of the pum window.

The redraw could be quite slow for many reasons, one possible reason is there are too many extmarks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants