gui_mch_update_tabline in Windows gvim is quadratic in the number of tabs. This
happens because the entire control is redrawn after every
InsertItem/SetItem/DeleteItem message. The delay starts to get *really*
noticeable at 60 open tabs or so (Windows 7).
Note that disabling redraws during the update is not enough - the code used
GetTabItemRect to check if the item is present; however, this forces the tab
control to recompute the layout after every change, which still results in
quadratic behavior.
The attached patch fixes the issue.
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
diff -r 61a7c3f01088 src/gui_w48.c
--- a/src/gui_w48.c Wed Oct 03 21:48:44 2012 +0200
+++ b/src/gui_w48.c Wed Oct 03 22:55:56 2012 -0700
@@ -2473,13 +2473,16 @@
tie.mask = TCIF_TEXT;
tie.iImage = -1;
+ /* Disable redraws for tab updates to eliminate O(N^2) draws. */
+ SendMessage(s_tabhwnd, WM_SETREDRAW, (WPARAM)FALSE, 0);
+
/* Add a label for each tab page. They all contain the same text area. */
for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, ++nr)
{
if (tp == curtab)
curtabidx = nr;
- if (!TabCtrl_GetItemRect(s_tabhwnd, nr, &rc))
+ if (nr >= TabCtrl_GetItemCount(s_tabhwnd))
{
/* Add the tab */
tie.pszText = "-Empty-";
@@ -2513,11 +2516,14 @@
}
/* Remove any old labels. */
- while (TabCtrl_GetItemRect(s_tabhwnd, nr, &rc))
+ while (nr < TabCtrl_GetItemCount(s_tabhwnd))
TabCtrl_DeleteItem(s_tabhwnd, nr);
if (TabCtrl_GetCurSel(s_tabhwnd) != curtabidx)
TabCtrl_SetCurSel(s_tabhwnd, curtabidx);
+
+ /* Re-enable redraws. This should trigger a repaint. */
+ SendMessage(s_tabhwnd, WM_SETREDRAW, (WPARAM)TRUE, 0);
}
/*