From: Yasuhiro Matsumoto Date: Fri, 13 Mar 2026 17:45:36 +0000 (+0000) Subject: patch 9.2.0152: concatenating strings is slow X-Git-Tag: v9.2.0152^0 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=16d421a4d95b45ebbcf47ab60173cdb1b87ce419;p=thirdparty%2Fvim.git patch 9.2.0152: concatenating strings is slow Problem: concatenating strings is slow Solution: Use grow_string_tv() to grow the existing string buffer in place when possible (Yasuhiro Matsumoto). closes: #19642 Signed-off-by: Yasuhiro Matsumoto Signed-off-by: Christian Brabandt --- diff --git a/src/eval.c b/src/eval.c index 551e8641cd..42719d9e57 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2639,6 +2639,28 @@ tv_op_number(typval_T *tv1, typval_T *tv2, char_u *op) return failed ? FAIL : OK; } +/* + * Append string "s2" to the string in "tv1". + * Returns OK if "tv1" was grown in place, FAIL otherwise. + */ + static int +grow_string_tv(typval_T *tv1, char_u *s2) +{ + if (tv1->v_type != VAR_STRING || tv1->vval.v_string == NULL) + return FAIL; + + size_t len1 = STRLEN(tv1->vval.v_string); + size_t len2 = STRLEN(s2); + char_u *p = vim_realloc(tv1->vval.v_string, len1 + len2 + 1); + + if (p == NULL) + return FAIL; + + mch_memmove(p + len1, s2, len2 + 1); + tv1->vval.v_string = p; + return OK; +} + /* * Handle "str1 .= str2" * Returns OK or FAIL. @@ -2648,13 +2670,18 @@ tv_op_string(typval_T *tv1, typval_T *tv2, char_u *op UNUSED) { char_u numbuf[NUMBUFLEN]; char_u *s; + char_u *s2; if (tv2->v_type == VAR_FLOAT) return FAIL; // str .= str + s2 = tv_get_string_buf(tv2, numbuf); + if (grow_string_tv(tv1, s2) == OK) + return OK; + s = tv_get_string(tv1); - s = concat_str(s, tv_get_string_buf(tv2, numbuf)); + s = concat_str(s, s2); clear_tv(tv1); tv1->v_type = VAR_STRING; tv1->vval.v_string = s; @@ -4371,6 +4398,10 @@ eval_concat_str(typval_T *tv1, typval_T *tv2) return FAIL; } + // When possible, grow the existing string in place to avoid alloc/free. + if (grow_string_tv(tv1, s2) == OK) + return OK; + p = concat_str(s1, s2); clear_tv(tv1); tv1->v_type = VAR_STRING; diff --git a/src/version.c b/src/version.c index 9969dc786c..78491aa866 100644 --- a/src/version.c +++ b/src/version.c @@ -734,6 +734,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 152, /**/ 151, /**/