From e1e92fea92ed80dd10ff0cb325433a97c1826b6a Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Sat, 2 May 2026 15:39:55 +0000 Subject: [PATCH] patch 9.2.0431: blob encoding can be improved MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Christian Brabandt --- src/json.c | 33 +++++++++++++++++++++------------ src/version.c | 2 ++ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/json.c b/src/json.c index b0d98a290e..a3e58043d8 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 0ce32fb2e4..9208a50785 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, /**/