Skip to content

Commit 78019df

Browse files
kawaii-Codechrisbra
authored andcommitted
patch 9.1.0055: formatting long lines is slow
Problem: formatting long lines is slow (kawaii-Code) Solution: optimize gq (internal_format) for long lines (kawaii-Code) Implemented two workarounds that significantly reduce the amount of pointless calls. Ideally the algorithm would be rewritten not to be n^2, but it's too complicated with too many corner cases. closes: #13914 Signed-off-by: kawaii-Code <nia.personal.0@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
1 parent 703f9bc commit 78019df

2 files changed

Lines changed: 26 additions & 6 deletions

File tree

src/textformat.c

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,18 @@ internal_format(
9090
colnr_T end_col;
9191
int wcc; // counter for whitespace chars
9292
int did_do_comment = FALSE;
93+
int first_pass;
9394

94-
virtcol = get_nolist_virtcol()
95-
+ char2cells(c != NUL ? c : gchar_cursor());
96-
if (virtcol <= (colnr_T)textwidth)
97-
break;
95+
// Cursor is currently at the end of line. No need to format
96+
// if line length is less than textwidth (8 * textwidth for
97+
// utf safety)
98+
if (curwin->w_cursor.col < 8 * textwidth)
99+
{
100+
virtcol = get_nolist_virtcol()
101+
+ char2cells(c != NUL ? c : gchar_cursor());
102+
if (virtcol <= (colnr_T)textwidth)
103+
break;
104+
}
98105

99106
if (no_leader)
100107
do_comments = FALSE;
@@ -144,9 +151,17 @@ internal_format(
144151
coladvance((colnr_T)textwidth);
145152
wantcol = curwin->w_cursor.col;
146153

147-
curwin->w_cursor.col = startcol;
154+
// If startcol is large (a long line), formatting takes too much
155+
// time. The algorithm is O(n^2), it walks from the end of the
156+
// line to textwidth border every time for each line break.
157+
//
158+
// Ceil to 8 * textwidth to optimize.
159+
curwin->w_cursor.col = startcol < 8 * textwidth ? startcol :
160+
8 * textwidth;
161+
148162
foundcol = 0;
149163
skip_pos = 0;
164+
first_pass = TRUE;
150165

151166
// Find position to break at.
152167
// Stop at first entered white when 'formatoptions' has 'v'
@@ -155,8 +170,11 @@ internal_format(
155170
|| curwin->w_cursor.lnum != Insstart.lnum
156171
|| curwin->w_cursor.col >= Insstart.col)
157172
{
158-
if (curwin->w_cursor.col == startcol && c != NUL)
173+
if (first_pass && c != NUL)
174+
{
159175
cc = c;
176+
first_pass = FALSE;
177+
}
160178
else
161179
cc = gchar_cursor();
162180
if (WHITECHAR(cc))

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,8 @@ static char *(features[]) =
704704

705705
static int included_patches[] =
706706
{ /* Add new patch number below this line */
707+
/**/
708+
55,
707709
/**/
708710
54,
709711
/**/

0 commit comments

Comments
 (0)