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 <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Yasuhiro Matsumoto
2026-05-02 15:39:55 +00:00
committed by Christian Brabandt
parent 2219c89013
commit e1e92fea92
2 changed files with 23 additions and 12 deletions
+21 -12
View 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;
+2
View File
@@ -729,6 +729,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
431,
/**/
430,
/**/