From 57282c62a0df04808d24d63a48be3774f3180763 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Mon, 2 Sep 2024 13:45:38 +0200 Subject: [PATCH] [flori/json] Optimize `fbuffer_inc_capa` On my `JSON.dump` benchmark it shows up as 6% of runtime, compared to 40% for `convert_UTF8_to_JSON`. Since the vast majority of the time this function is called we still have some buffer capacity, we might as well check that first and skip the expensive loop etc. With this change my profiler now report this function as 0.7%, so almost 10x better. https://github.com/flori/json/commit/a7206bf2db --- ext/json/fbuffer/fbuffer.h | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/ext/json/fbuffer/fbuffer.h b/ext/json/fbuffer/fbuffer.h index 7ece0cee95..1fb9d66700 100644 --- a/ext/json/fbuffer/fbuffer.h +++ b/ext/json/fbuffer/fbuffer.h @@ -66,6 +66,10 @@ static FBuffer *fbuffer_dup(FBuffer *fb); static VALUE fbuffer_to_s(FBuffer *fb); #endif +#ifndef RB_UNLIKELY +#define RB_UNLIKELY(expr) expr +#endif + static FBuffer *fbuffer_alloc(unsigned long initial_length) { FBuffer *fb; @@ -87,20 +91,22 @@ static void fbuffer_clear(FBuffer *fb) fb->len = 0; } -static void fbuffer_inc_capa(FBuffer *fb, unsigned long requested) +static inline void fbuffer_inc_capa(FBuffer *fb, unsigned long requested) { - unsigned long required; + if (RB_UNLIKELY(requested > fb->capa - fb->len)) { + unsigned long required; - if (!fb->ptr) { - fb->ptr = ALLOC_N(char, fb->initial_length); - fb->capa = fb->initial_length; - } + if (RB_UNLIKELY(!fb->ptr)) { + fb->ptr = ALLOC_N(char, fb->initial_length); + fb->capa = fb->initial_length; + } - for (required = fb->capa; requested > required - fb->len; required <<= 1); + for (required = fb->capa; requested > required - fb->len; required <<= 1); - if (required > fb->capa) { - REALLOC_N(fb->ptr, char, required); - fb->capa = required; + if (required > fb->capa) { + REALLOC_N(fb->ptr, char, required); + fb->capa = required; + } } }