]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0431: blob encoding can be improved v9.2.0431
authorYasuhiro Matsumoto <mattn.jp@gmail.com>
Sat, 2 May 2026 15:39:55 +0000 (15:39 +0000)
committerChristian Brabandt <cb@256bit.org>
Sat, 2 May 2026 15:39:55 +0000 (15:39 +0000)
Problem:  blob encoding can be improved
Solution: Speed up blob encoding by avoiding per-byte ga_append()
          (Yasuhiro Matsumoto)

Replace the per-byte ga_append loop in the VAR_BLOB branch of
json_encode_item() with a single ga_grow for the worst case
(2 + 4 * blen) and direct writes through a local pointer. Also
read blob bytes through a local char_u* instead of going through
blob_get() for each byte.

Benchmark (1 MiB blob, 5 iterations, total seconds, median of 3 runs):

| byte distribution | Before | After | Speedup |
|---|---:|---:|---:|
| 1-digit (0–9)     | 0.0254 | 0.0174 | 1.46x |
| 2-digit (10–99)   | 0.0344 | 0.0064 | 5.38x |
| 3-digit (100–255) | 0.0539 | 0.0102 | 5.28x |
| mixed (0–255)     | 0.0335 | 0.0093 | 3.60x |

closes: #20113

Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/json.c
src/version.c

index b0d98a290e3f04db6b85e230aee973e58ca60b30..a3e58043d8891aef4d1e74d8ccc003f4f4dfe174 100644 (file)
@@ -369,29 +369,38 @@ json_encode_item(garray_T *gap, typval_T *val, int copyID, int options)
                GA_CONCAT_LITERAL(gap, "[]");
            else
            {
-               ga_append(gap, '[');
-               for (i = 0; i < b->bv_ga.ga_len; i++)
+               int     blen = b->bv_ga.ga_len;
+               char_u  *src;
+               char_u  *dst;
+
+               // Worst case: '[' + ']' + per-byte 3 digits + comma = 2 + 4*blen
+               if (ga_grow(gap, 2 + 4 * blen) == FAIL)
+                   goto theend;
+               src = (char_u *)b->bv_ga.ga_data;
+               dst = (char_u *)gap->ga_data + gap->ga_len;
+               *dst++ = '[';
+               for (i = 0; i < blen; i++)
                {
-                   int     byte = blob_get(b, i);
+                   int     byte = src[i];
 
                    if (i > 0)
-                       ga_append(gap, ',');
-                   // blob bytes are 0-255, use simple conversion
+                       *dst++ = ',';
                    if (byte >= 100)
                    {
-                       ga_append(gap, '0' + byte / 100);
-                       ga_append(gap, '0' + (byte / 10) % 10);
-                       ga_append(gap, '0' + byte % 10);
+                       *dst++ = '0' + byte / 100;
+                       *dst++ = '0' + (byte / 10) % 10;
+                       *dst++ = '0' + byte % 10;
                    }
                    else if (byte >= 10)
                    {
-                       ga_append(gap, '0' + byte / 10);
-                       ga_append(gap, '0' + byte % 10);
+                       *dst++ = '0' + byte / 10;
+                       *dst++ = '0' + byte % 10;
                    }
                    else
-                       ga_append(gap, '0' + byte);
+                       *dst++ = '0' + byte;
                }
-               ga_append(gap, ']');
+               *dst++ = ']';
+               gap->ga_len = (int)(dst - (char_u *)gap->ga_data);
            }
            break;
 
index 0ce32fb2e4c774c6f17096a3658b78a00ecfb9f4..9208a50785b5878b79998e7e95ed1badbc62a5a9 100644 (file)
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    431,
 /**/
     430,
 /**/