equalsraf / neovim-qt

Neovim client library and GUI, in Qt5.
https://github.com/equalsraf/neovim-qt/wiki
ISC License
1.86k stars 171 forks source link

Potential Bug: Abnormal CPU usage when the window is small #1090

Closed Eiko-Tokura closed 8 months ago

Eiko-Tokura commented 9 months ago

Problem: when the nvim-qt window is smaller than two lines, it will occupy abnormal high amount of cpu forever. When you resize it back, it comes back to normal.

Typically people don't use nvim-qt with this small window size, but sometimes in window managers, it is unavoidable for windows to be shrinked to a small size to be viewed later.

This problem can be recreated 100% on my multiple machines.

nvim does not have this issue. I'm not sure if this is the bug of qt.

system: arch linux, wm: xmonad nvim-qt version: 0.2.18-1 installed from arch repository

1706382534 1706382524

equalsraf commented 9 months ago

Confirmed.

Internally it looks likes we enter some kind of loop where messages keep being sent back and forth between the UI and neovim.

The calls being made are (30 UI_TRY_RESIZE, 48 VIM_GET_OPTION)

So it seems we enter a loop where

A call to resizeNeovim can happen

Other notes

equalsraf commented 9 months ago

With some debug prints:

calling resizeNeovim() from mainwindow (after neovim resize?) QSize(762, 82)
resizeNeovim() from 3  =>  2
-- setting pending resize from QSize(-1, -1) to 2
calling resizeNeovim() after pending resize
resizeNeovim() from 3  =>  2
-- making call ui_try_resize 2
handleResize() 69 3
calling resizeNeovim() from mainwindow (after neovim resize?) QSize(762, 82)
resizeNeovim() from 3  =>  2
-- setting pending resize from QSize(-1, -1) to 2
calling resizeNeovim() after pending resize
resizeNeovim() from 3  =>  2
-- making call ui_try_resize 2
handleResize() 69 3
calling resizeNeovim() from mainwindow (after neovim resize?) QSize(762, 82)
resizeNeovim() from 3  =>  2
-- setting pending resize from QSize(-1, -1) to 2
calling resizeNeovim() after pending resize
resizeNeovim() from 3  =>  2
-- making call ui_try_resize 2
handleResize() 69 3
calling resizeNeovim() from mainwindow (after neovim resize?) QSize(762, 82)
resizeNeovim() from 3  =>  2
-- setting pending resize from QSize(-1, -1) to 2
calling resizeNeovim() after pending resize
resizeNeovim() from 3  =>  2
-- making call ui_try_resize 2
handleResize() 69 3
calling resizeNeovim() from mainwindow (after neovim resize?) QSize(762, 82)
resizeNeovim() from 3  =>  2
-- setting pending resize from QSize(-1, -1) to 2

looks liks

  1. call to resizeNeovim() from 3 rows to 2 rows
  2. this resize is deferred (because there is a previous resize in progress)
  3. then the resize that was deferred is applied (to 2 rows)
  4. effective call to ui_try_resize happens (2 rows)
  5. neovim event handleResize() with 3 rows - this triggers resizeNeovim again
equalsraf commented 9 months ago

It is not surprising that neovim cannot be resized to under 3 rows with my settings, since it needs one row for the buffer, one for the ruler, and one for the command line.

I think we can avoid this loop by preventing a pending resize request from using the same columns/rows as the ongoing one.