# HG changeset patch # User Bram Moolenaar # Date 1616762702 -3600 # Node ID f49f80a0905d305f90729582d240ee24f1d616e2 # Parent b19ab4d458ab195531762d4f56d2a2353e8fcbe5 patch 8.2.2654: Vim9: getting a character from a string can be slow Commit: https://github.com/vim/vim/commit/ff871400461183010d3ab98f3f326e4bb75e221b Author: Bram Moolenaar Date: Fri Mar 26 13:34:05 2021 +0100 patch 8.2.2654: Vim9: getting a character from a string can be slow Problem: Vim9: getting a character from a string can be slow. Solution: Avoid a function call to get the character byte size. (https://github.com/vim/vim/issues/8000) diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2654, +/**/ 2653, /**/ 2652, diff --git a/src/vim9execute.c b/src/vim9execute.c --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1067,13 +1067,22 @@ char_from_string(char_u *str, varnumber_ return NULL; slen = STRLEN(str); - // do the same as for a list: a negative index counts from the end + // Do the same as for a list: a negative index counts from the end. + // Optimization to check the first byte to be below 0x80 (and no composing + // character follows) makes this a lot faster. if (index < 0) { int clen = 0; for (nbyte = 0; nbyte < slen; ++clen) - nbyte += mb_ptr2len(str + nbyte); + { + if (str[nbyte] < 0x80 && str[nbyte + 1] < 0x80) + ++nbyte; + else if (enc_utf8) + nbyte += utfc_ptr2len(str + nbyte); + else + nbyte += mb_ptr2len(str + nbyte); + } nchar = clen + index; if (nchar < 0) // unlike list: index out of range results in empty string @@ -1081,7 +1090,14 @@ char_from_string(char_u *str, varnumber_ } for (nbyte = 0; nchar > 0 && nbyte < slen; --nchar) - nbyte += mb_ptr2len(str + nbyte); + { + if (str[nbyte] < 0x80 && str[nbyte + 1] < 0x80) + ++nbyte; + else if (enc_utf8) + nbyte += utfc_ptr2len(str + nbyte); + else + nbyte += mb_ptr2len(str + nbyte); + } if (nbyte >= slen) return NULL; return vim_strnsave(str + nbyte, mb_ptr2len(str + nbyte));