]> granicus.if.org Git - vim/commitdiff
patch 8.0.1774: reading very long lines can be slow v8.0.1774
authorBram Moolenaar <Bram@vim.org>
Sun, 29 Apr 2018 11:34:47 +0000 (13:34 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 29 Apr 2018 11:34:47 +0000 (13:34 +0200)
Problem:    Reading very long lines can be slow.
Solution:   Read up to 1 Mbyte at a time to avoid a lot of copying.  Add a
            check for going over the column limit.

src/fileio.c
src/version.c

index 35f4fd2c2b26ace9183300a1dea5645fe89547ee..6b48c39d3220bce446e31cc2891a596d197badca 100644 (file)
@@ -1209,28 +1209,42 @@ retry:
         * The amount is limited by the fact that read() only can read
         * upto max_unsigned characters (and other things).
         */
-#if VIM_SIZEOF_INT <= 2
-       if (linerest >= 0x7ff0)
+       if (!skip_read)
        {
-           ++split;
-           *ptr = NL;              /* split line by inserting a NL */
-           size = 1;
-       }
-       else
-#endif
-       {
-           if (!skip_read)
-           {
 #if VIM_SIZEOF_INT > 2
 # if defined(SSIZE_MAX) && (SSIZE_MAX < 0x10000L)
                size = SSIZE_MAX;                   /* use max I/O size, 52K */
 # else
-               size = 0x10000L;                    /* use buffer >= 64K */
+               /* Use buffer >= 64K.  Add linerest to double the size if the
+                * line gets very long, to avoid a lot of copying. But don't
+                * read more than 1 Mbyte at a time, so we can be interrupted.
+                */
+               size = 0x10000L + linerest;
+               if (size > 0x100000L)
+                   size = 0x100000L;
 # endif
 #else
                size = 0x7ff0L - linerest;          /* limit buffer to 32K */
 #endif
+       }
 
+       /* Protect against the argument of lalloc() going negative. */
+       if (
+#if VIM_SIZEOF_INT <= 2
+           linerest >= 0x7ff0
+#else
+           size < 0 || size + linerest + 1 < 0 || linerest >= MAXCOL
+#endif
+          )
+       {
+           ++split;
+           *ptr = NL;              /* split line by inserting a NL */
+           size = 1;
+       }
+       else
+       {
+           if (!skip_read)
+           {
                for ( ; size >= 10; size = (long)((long_u)size >> 1))
                {
                    if ((new_buffer = lalloc((long_u)(size + linerest + 1),
index 5d75dabf571bc6f47b4770cfa5f686914b2f4e34..10e446a69d85d76554e67205c03bceddf0243ce6 100644 (file)
@@ -761,6 +761,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1774,
 /**/
     1773,
 /**/