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

High CPU usage w/conceallevel set #39

Open
romgrk opened this issue Oct 30, 2020 · 12 comments
Open

High CPU usage w/conceallevel set #39

romgrk opened this issue Oct 30, 2020 · 12 comments
Labels
bug Something isn't working has-workaround upstream-issue Issue in Neovim

Comments

@romgrk
Copy link

romgrk commented Oct 30, 2020

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 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:
Screenshot from 2020-10-30 15-29-34

@smolck
Copy link
Owner

smolck commented Oct 30, 2020

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.

@romgrk
Copy link
Author

romgrk commented Oct 30, 2020

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:
Screenshot from 2020-10-30 15-46-08

@romgrk
Copy link
Author

romgrk commented Oct 30, 2020

By the way, to inspect what neovim does you can use gdb: start with sudo gdb, then execute attach xxxxwhere 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

@romgrk
Copy link
Author

romgrk commented Oct 30, 2020

Also very useful watch -l variablename to make a breakpoint when that variable's value is changed. (eg watch -l must_redraw).

@smolck
Copy link
Owner

smolck commented Oct 30, 2020

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.

@romgrk
Copy link
Author

romgrk commented Oct 30, 2020

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.

@smolck
Copy link
Owner

smolck commented Oct 30, 2020

Hmm, I'm still not sure what is causing the 100% CPU usage. I can't reproduce it.

@romgrk
Copy link
Author

romgrk commented Oct 30, 2020

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.

@romgrk
Copy link
Author

romgrk commented Oct 30, 2020

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:

https://github.com/neovim/neovim/blob/98024853f4755f51e82526b45484bae0ec6042ba/src/nvim/normal.c#L1248-L1253

https://github.com/neovim/neovim/blob/98024853f4755f51e82526b45484bae0ec6042ba/src/nvim/screen.c#L654-L676

I'll open an issue in neovim to check what's the opinion on this.

@smolck
Copy link
Owner

smolck commented Oct 30, 2020

So is there anything that needs to be handled in uivonim, or is this all an upstream issue?

@romgrk
Copy link
Author

romgrk commented Oct 30, 2020

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:

  • remove statusline plugins & disable it
  • set conceallevel=0 & remove plugins using it

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.

@smolck smolck added upstream-issue Issue in Neovim bug Something isn't working labels Oct 30, 2020
@smolck smolck pinned this issue Oct 30, 2020
@smolck smolck changed the title Performance: lot of time spent in win_update in neovim High CPU usage w/conceallevel set Oct 30, 2020
@smolck
Copy link
Owner

smolck commented Oct 30, 2020

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working has-workaround upstream-issue Issue in Neovim
Projects
None yet
Development

No branches or pull requests

2 participants