# HG changeset patch # User Bram Moolenaar # Date 1653662704 -7200 # Node ID f9775679df1fe1690959f1052c1f4aa64194ebd9 # Parent 922c555e7aadd6e0cc4f88aba3b8b401f5df59f5 patch 8.2.5028: syntax regexp matching can be slow Commit: https://github.com/vim/vim/commit/02e8d4e4ffcdd6ee919e19692d591da8e18a565d Author: Bram Moolenaar Date: Fri May 27 15:35:28 2022 +0100 patch 8.2.5028: syntax regexp matching can be slow 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) diff --git a/src/regexp_bt.c b/src/regexp_bt.c --- a/src/regexp_bt.c +++ b/src/regexp_bt.c @@ -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)) diff --git a/src/regexp_nfa.c b/src/regexp_nfa.c --- a/src/regexp_nfa.c +++ b/src/regexp_nfa.c @@ -5649,11 +5649,27 @@ find_match_text(colnr_T startcol, int re 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; } diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -735,6 +735,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 5028, +/**/ 5027, /**/ 5026,