Commit: patch 9.2.0431: blob encoding can be improved

3 views
Skip to first unread message

Christian Brabandt

unread,
May 2, 2026, 11:45:15 AMMay 2
to vim...@googlegroups.com
patch 9.2.0431: blob encoding can be improved

Commit: https://github.com/vim/vim/commit/e1e92fea92ed80dd10ff0cb325433a97c1826b6a
Author: Yasuhiro Matsumoto <matt...@gmail.com>
Date: Sat May 2 15:39:55 2026 +0000

patch 9.2.0431: blob encoding can be improved

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 <matt...@gmail.com>
Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/json.c b/src/json.c
index b0d98a290..a3e58043d 100644
--- a/src/json.c
+++ b/src/json.c
@@ -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;

diff --git a/src/version.c b/src/version.c
index 0ce32fb2e..9208a5078 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 431,
/**/
430,
/**/
Reply all
Reply to author
Forward
0 new messages