From 97b5df11435d60d4dcdeb9474275cfc694d43b1e Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Sun, 24 Aug 2025 17:39:10 +0200 Subject: [ruby/json] Optimize `fbuffer_append_str_repeat` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Helps with pretty printting performance: ``` == Encoding activitypub.json (52595 bytes) ruby 3.4.2 (2025-02-15 revision https://github.com/ruby/json/commit/d2930f8e7a) +YJIT +PRISM [arm64-darwin24] Warming up -------------------------------------- after 1.746k i/100ms Calculating ------------------------------------- after 17.481k (± 1.0%) i/s (57.20 μs/i) - 89.046k in 5.094341s Comparison: before: 16038.4 i/s after: 17481.1 i/s - 1.09x faster == Encoding citm_catalog.json (500298 bytes) ruby 3.4.2 (2025-02-15 revision https://github.com/ruby/json/commit/d2930f8e7a) +YJIT +PRISM [arm64-darwin24] Warming up -------------------------------------- after 60.000 i/100ms Calculating ------------------------------------- after 608.157 (± 2.3%) i/s (1.64 ms/i) - 3.060k in 5.034238s Comparison: before: 525.3 i/s after: 608.2 i/s - 1.16x faster == Encoding twitter.json (466906 bytes) ruby 3.4.2 (2025-02-15 revision https://github.com/ruby/json/commit/d2930f8e7a) +YJIT +PRISM [arm64-darwin24] Warming up -------------------------------------- after 160.000 i/100ms Calculating ------------------------------------- after 1.606k (± 0.5%) i/s (622.70 μs/i) - 8.160k in 5.081406s Comparison: before: 1410.3 i/s after: 1605.9 i/s - 1.14x faster ``` https://github.com/ruby/json/commit/f0dda861c5 --- ext/json/fbuffer/fbuffer.h | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/ext/json/fbuffer/fbuffer.h b/ext/json/fbuffer/fbuffer.h index dc40dec7f5..247a0de470 100644 --- a/ext/json/fbuffer/fbuffer.h +++ b/ext/json/fbuffer/fbuffer.h @@ -169,12 +169,17 @@ static inline void fbuffer_inc_capa(FBuffer *fb, unsigned long requested) } } -static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len) +static inline void fbuffer_append_reserved(FBuffer *fb, const char *newstr, unsigned long len) +{ + MEMCPY(fb->ptr + fb->len, newstr, char, len); + fbuffer_consumed(fb, len); +} + +static inline void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len) { if (len > 0) { fbuffer_inc_capa(fb, len); - MEMCPY(fb->ptr + fb->len, newstr, char, len); - fbuffer_consumed(fb, len); + fbuffer_append_reserved(fb, newstr, len); } } @@ -202,13 +207,15 @@ static void fbuffer_append_str(FBuffer *fb, VALUE str) static void fbuffer_append_str_repeat(FBuffer *fb, VALUE str, size_t repeat) { + const char *newstr = StringValuePtr(str); unsigned long len = RSTRING_LEN(str); - size_t total = repeat * len; - fbuffer_inc_capa(fb, total); - + fbuffer_inc_capa(fb, repeat * len); while (repeat) { - fbuffer_append_str(fb, str); +#ifdef JSON_DEBUG + fb->requested = len; +#endif + fbuffer_append_reserved(fb, newstr, len); repeat--; } } -- cgit v1.2.3