patch 8.2.5028: syntax regexp matching can be slow v8.2.5028
authorBram Moolenaar <Bram@vim.org>
Fri, 27 May 2022 14:35:28 +0000 (15:35 +0100)
committerBram Moolenaar <Bram@vim.org>
Fri, 27 May 2022 14:35:28 +0000 (15:35 +0100)
Problem:    Syntax regexp matching can be slow.
Solution:   Adjust the counters for checking the timeout to check about once
            per msec. (closes #10487, closes #2712)

src/regexp_bt.c
src/regexp_nfa.c
src/version.c

index 698ff043ea04de76b76099fb21a1a97c8bba8811..5bf0e0c4eb95b80e1c59e103f2da9d28b15c0707 100644 (file)
@@ -3271,8 +3271,10 @@ regmatch(
            break;
        }
 #ifdef FEAT_RELTIME
-       // Check for timeout once in a 100 times to avoid overhead.
-       if (tm != NULL && ++tm_count == 100)
+       // Check for timeout once in 250 times to avoid excessive overhead from
+       // reading the clock.  The value has been picked to check about once
+       // per msec on a modern CPU.
+       if (tm != NULL && ++tm_count == 250)
        {
            tm_count = 0;
            if (profile_passed_limit(tm))
@@ -3313,7 +3315,7 @@ regmatch(
        op = OP(scan);
        // Check for character class with NL added.
        if (!rex.reg_line_lbr && WITH_NL(op) && REG_MULTI
-                            && *rex.input == NUL && rex.lnum <= rex.reg_maxline)
+                          && *rex.input == NUL && rex.lnum <= rex.reg_maxline)
        {
            reg_nextline();
        }
@@ -4990,8 +4992,10 @@ bt_regexec_both(
            else
                ++col;
 #ifdef FEAT_RELTIME
-           // Check for timeout once in a twenty times to avoid overhead.
-           if (tm != NULL && ++tm_count == 20)
+           // Check for timeout once in 500 times to avoid excessive overhead
+           // from reading the clock.  The value has been picked to check
+           // about once per msec on a modern CPU.
+           if (tm != NULL && ++tm_count == 500)
            {
                tm_count = 0;
                if (profile_passed_limit(tm))
index 511b90483422a958c2e194243f9631971ae274c1..1e7cd9b4649230b6372eaf63f1d5c88ce8a59217 100644 (file)
@@ -5649,11 +5649,27 @@ find_match_text(colnr_T startcol, int regstart, char_u *match_text)
     static int
 nfa_did_time_out()
 {
-    if (nfa_time_limit != NULL && profile_passed_limit(nfa_time_limit))
+    static int tm_count = 0;
+
+    // Check for timeout once in 800 times to avoid excessive overhead from
+    // reading the clock.  The value has been picked to check about once per
+    // msec on a modern CPU.
+    if (nfa_time_limit != NULL)
     {
-       if (nfa_timed_out != NULL)
-           *nfa_timed_out = TRUE;
-       return TRUE;
+       if (tm_count == 800)
+       {
+           if (profile_passed_limit(nfa_time_limit))
+           {
+               if (nfa_timed_out != NULL)
+                   *nfa_timed_out = TRUE;
+               return TRUE;
+           }
+           // Only reset the count when not timed out, so that when it did
+           // timeout it keeps timing out until the time limit is changed.
+           tm_count = 0;
+       }
+       else
+           ++tm_count;
     }
     return FALSE;
 }
index 3cc224eef2b2f34246cb052515e9f903a7827a65..480ff28c7ccc1e7e6cd56b3e59f0159b464d2ee4 100644 (file)
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    5028,
 /**/
     5027,
 /**/