aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbfredl <bjorn.linse@gmail.com>2023-02-08 16:24:33 +0100
committerbfredl <bjorn.linse@gmail.com>2023-02-08 18:02:55 +0100
commit28e26e05bc4cd2bd8e1abc2dd4d720fd9199456d (patch)
treeb3a2935a3b499d07198dfc07d77c8bc85ecfbe8e
parent625e990976540a0e2d2bccb98deb57d0919d1e89 (diff)
downloadrneovim-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.c10
-rw-r--r--src/nvim/ui.h2
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.