Open romgrk opened 3 years ago
Thank you for opening this issue!
The first thing that jumped is that it spent a lot of time in build_stl_str_hl, the function that renders the statusline. I disabled the code in my config doing that, and the CPU usage dropped to ~70-80%, so any vimscript for the statusline needs to be disabled.
Where is this function/what did you disable?
After inspection, it seems that neovim is doing A LOT of win_update() even though I'm sitting still and touching nothing. When there isn't any user input, neovim shouldn't be doing anything! Maybe is there something in uivonim continuously pinging neovim? Here are a few backtraces from interrupting the running process at random moments:
Hmm, I have no idea what could be causing this. Do you have any ideas/suspicions yourself as to what might be causing this? I might have to go digging through the neovim source to see what causes win_update
to be called.
I just disabled my custom statusline rendering code in vimscript. I'm inspecting the source and here is the call stack for win_update()
:
#0 0x00007f4fc35b02ba in __strcmp_avx2 () from /usr/lib/libc.so.6
#1 0x0000557ca08e48bf in syn_name2id (name=0x557ca0a54ddd "Conceal") at ../src/nvim/syntax.c:7406
#2 0x0000557ca087b217 in win_line (wp=0x557ca258f270, lnum=494, startrow=15, endrow=27, nochange=false, number_only=false, foldinfo=..., providers=0x7ffed5f13200)
at ../src/nvim/screen.c:2990
#3 0x0000557ca0876f55 in win_update (wp=0x557ca258f270, providers=0x7ffed5f133b0) at ../src/nvim/screen.c:1546
#4 0x0000557ca0874095 in update_screen (type=10) at ../src/nvim/screen.c:595
#5 0x0000557ca07fca81 in normal_redraw (s=0x7ffed5f13510) at ../src/nvim/normal.c:1263
#6 0x0000557ca07fccb2 in normal_check (state=0x7ffed5f13510) at ../src/nvim/normal.c:1352
#7 0x0000557ca08cff3d in state_enter (s=0x7ffed5f13510) at ../src/nvim/state.c:28
#8 0x0000557ca07fa927 in normal_enter (cmdwin=false, noexmode=false) at ../src/nvim/normal.c:463
#9 0x0000557ca07b6d92 in main (argc=6, argv=0x7ffed5f138a8) at ../src/nvim/main.c:557
I also see that redraw_statusline()
is called inside normal_redraw()
. Maybe a PR should be opened in neovim to not call redraw_statusline()
if the statusline is handled by the UI:
By the way, to inspect what neovim does you can use gdb
: start with sudo gdb
, then execute attach xxxx
where xxxx is neovim's PID that you can get with echom getpid()
. Then Ctrl+c interrupts neovim and let's you inspect where it's at. Use bt
to get the backtrace, f
to jump to a different frame (function), and p variable
to inspect the content of a variable. cheat sheet
Also very useful watch -l variablename
to make a breakpoint when that variable's value is changed. (eg watch -l must_redraw
).
Interesting, I don't seem to get the same level of CPU usage . . .
Thank you for the gdb tips! Didn't know those things.
I also see that redraw_statusline() is called inside normal_redraw(). Maybe a PR should be opened in neovim to not call redraw_statusline() if the statusline is handled by the UI.
Currently ext_statusline is not implemented in neovim, so that's probably why; there's no way to tell Neovim that an external statusline is used (afaik). Currently, uivonim just doesn't draw the statusline.
Currently ext_statusline is not implemented in neovim, so that's probably why; there's no way to tell Neovim that an external statusline is used (afaik). Currently, uivonim just doesn't draw the statusline.
Maybe tell neovim you do it, but don't do it? It's ok to lie.
Ok, so I've found another performance issue: the interaction of plugin "Yggdroot/indentLine" with this code: https://github.com/neovim/neovim/blob/master/src/nvim/normal.c#L1248-L1253 The plugin uses concealed text to show indent lines, and it seems to confuse neovim into thinking it should redraw. This also probably needs to be opened as an issue on neovim, because nothing changes here so no redraw should happen.
Hmm, I'm still not sure what is causing the 100% CPU usage. I can't reproduce it.
After disabling what was causing the 2 issues above (the statusline and the indent-lines using concealed text), when I interrupt neovim randomly it is sometimes in epoll_wait
, which is the expected behaviour, but still at 40% CPU. There is probably more things triggering redraws, I'll inspect a bit more.
After more inspection, it seems that neovim does a redraw if 'conceallevel'
is more than zero and if the current line might be concealed. The problem is the code that checks if the line is concealed doesn't check if the current line is actually concealed: it only checks if the current mode is in 'concealcursor'
. Setting 'conceallevel'
to zero brings CPU usage to negligible levels and neovim, when interrupted, is consistently in epoll_wait()
, the expected behavior.
Mentioned code:
I'll open an issue in neovim to check what's the opinion on this.
So is there anything that needs to be handled in uivonim, or is this all an upstream issue?
I would at least document the 2 perfomance issues on the readme, idk if you have a "before trying uivonim" section but it would be a good place to put this:
You could warn in uivonim if either of those things are set as it's causing a very scarry performance issue. First time I opened uivonim I didn't try it for more than 5 seconds.
I've updated the README to mention the conceallevel
problem, but I'm not sure why the statusline would cause that much higher CPU usage than the normal TUI, even if it is being drawn by uivonim.
First thing I noticed is that when I open uivonim I have nvim running at 100% CPU.
The first thing that jumped is that it spent a lot of time in
build_stl_str_hl
, the function that renders the statusline. I disabled the code in my config doing that, and the CPU usage dropped to ~70-80%, so any vimscript for the statusline needs to be disabled.After inspection, it seems that neovim is doing A LOT of![Screenshot from 2020-10-30 15-29-34](https://user-images.githubusercontent.com/1423607/97749308-37ae9580-1ac5-11eb-815c-7dfcc0c30386.png)
win_update()
even though I'm sitting still and touching nothing. When there isn't any user input, neovim shouldn't be doing anything! Maybe is there something in uivonim continuously pinging neovim? Here are a few backtraces from interrupting the running process at random moments: