diff options
author | bfredl <bjorn.linse@gmail.com> | 2023-02-08 16:24:33 +0100 |
---|---|---|
committer | bfredl <bjorn.linse@gmail.com> | 2023-02-08 18:02:55 +0100 |
commit | 28e26e05bc4cd2bd8e1abc2dd4d720fd9199456d (patch) | |
tree | b3a2935a3b499d07198dfc07d77c8bc85ecfbe8e | |
parent | 625e990976540a0e2d2bccb98deb57d0919d1e89 (diff) | |
download | rneovim-28e26e05bc4cd2bd8e1abc2dd4d720fd9199456d.tar.gz rneovim-28e26e05bc4cd2bd8e1abc2dd4d720fd9199456d.tar.bz2 rneovim-28e26e05bc4cd2bd8e1abc2dd4d720fd9199456d.zip |
perf(ui): mitigate redraw latency regression from TUI refactor
While the new RPC encoder/decoder implementation in general should have
less overhead than the deleted UIBridge serializer previously used for
the TUI, it regresses on redraw latency in one important aspect.
The old bridge implementation allowed the TUI to process a
previous screen line internally in parallel with the main thread
rendering the next one in win_line etc. As printing the escape
sequences in highlighted cells has a considerable hit in profiles,
this has a substantial effect on redraw latency. The RPC implementation,
however, waits with sending any data until either a flush, or the buffer is full.
This change lowers the granularity of communication again, using an
adjustable threshold counted in number of cell events (discounting
long repeats and clearing as maximum a single extra event).
The current value is guesstimated to something simple on a reasonable
scale, which should be bigger than a single line, but multiple events
for a big multi-window screen.
-rw-r--r-- | src/nvim/api/ui.c | 10 | ||||
-rw-r--r-- | src/nvim/ui.h | 2 |
2 files changed, 12 insertions, 0 deletions
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index e67607a7e4..3ad625234c 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -202,6 +202,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona data->flushed_events = false; data->ncalls_pos = NULL; data->ncalls = 0; + data->ncells_pending = 0; data->buf_wptr = data->buf; data->temp_buf = NULL; data->wildmenu_active = false; @@ -854,18 +855,25 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int mpack_uint(buf, repeat); } } + data->ncells_pending += MIN(repeat, 2); last_hl = attrs[i]; repeat = 0; } } if (endcol < clearcol) { nelem++; + data->ncells_pending += 1; mpack_array(buf, 3); mpack_str(buf, " "); mpack_uint(buf, (uint32_t)clearattr); mpack_uint(buf, (uint32_t)(clearcol - endcol)); } mpack_w2(&lenpos, nelem); + + if (data->ncells_pending > 500) { + // pass of cells to UI to let it start processing them + remote_ui_flush_buf(ui); + } } else { for (int i = 0; i < endcol - startcol; i++) { remote_ui_cursor_goto(ui, row, startcol + i); @@ -917,6 +925,8 @@ void remote_ui_flush_buf(UI *ui) // we have sent events to the client, but possibly not yet the final "flush" // event. data->flushed_events = true; + + data->ncells_pending = 0; } /// An intentional flush (vsync) when Nvim is finished redrawing the screen diff --git a/src/nvim/ui.h b/src/nvim/ui.h index 9140a9f1f3..e83f93eb07 100644 --- a/src/nvim/ui.h +++ b/src/nvim/ui.h @@ -79,6 +79,8 @@ typedef struct { uint32_t ncalls; ///< number of calls made to the current event (plus one for the name!) bool flushed_events; ///< events where sent to client without "flush" event + size_t ncells_pending; ///< total number of cells since last buffer flush + int hl_id; // Current highlight for legacy put event. Integer cursor_row, cursor_col; // Intended visible cursor position. |