Git development
 help / color / mirror / Atom feed
From: "René Scharfe" <l.s.r@web.de>
To: Jeff King <peff@peff.net>
Cc: git@vger.kernel.org
Subject: Re: [PATCH 1/4] strbuf: add strbuf_add_uint()
Date: Wed, 13 May 2026 19:46:11 +0200	[thread overview]
Message-ID: <9e0b4f9f-ffcb-4dad-bd4f-295bbc011a1e@web.de> (raw)
In-Reply-To: <20260513162232.GB103037@coredump.intra.peff.net>

On 5/13/26 6:22 PM, Jeff King wrote:
> On Tue, May 12, 2026 at 09:32:09PM +0200, René Scharfe wrote:
> 
>> The three variants were close in my tests, the no-copy variant slightly
>> winning on Apple silicon, but losing slightly more on an AMD Ryzen
>> laptop CPU.  So I went with the solid choice of using an on-stack
>> buffer, same as in printf(3) (at least on BSD).  Buffering at the end of
>> the strbuf was not really faster; perhaps memmove(3) is just that much
>> slower than memcpy(3).
> 
> I'm not sure if you did these tests initially, or if I nerd-sniped you
> into it. Either way, I am happy to be able to hear the results. ;)

Did them before I sent the series.

>> Perhaps an optimized decimal_width() could change the picture somewhat,
>> but I don't expect a big win.  On the other hand I just told you how
>> unreliable my expectations are, so there might be treasure after all. :)
> 
> I got identical times for cat-file's %(objectsize:disk) running your
> version against the one below.

Similar here (git_stack is this series, git_clz is your patch on top,
git_dec uses pager.c::decimal_width()):

Benchmark 1: ./git_stack cat-file --batch-all-objects --batch-check='%(objectsize:disk)'
  Time (mean ± σ):     383.5 ms ±   0.8 ms    [User: 374.7 ms, System: 7.6 ms]
  Range (min … max):   382.2 ms … 384.7 ms    10 runs

Benchmark 2: ./git_dec cat-file --batch-all-objects --batch-check='%(objectsize:disk)'
  Time (mean ± σ):     382.5 ms ±   1.0 ms    [User: 373.9 ms, System: 7.5 ms]
  Range (min … max):   381.2 ms … 384.7 ms    10 runs

Benchmark 3: ./git_clz cat-file --batch-all-objects --batch-check='%(objectsize:disk)'
  Time (mean ± σ):     382.5 ms ±   0.5 ms    [User: 373.7 ms, System: 7.7 ms]
  Range (min … max):   381.9 ms … 383.6 ms    10 runs

> Not wanting to figure out all of the
> off-by-one corner cases myself, I checked stack overflow for an easy
> recipe but couldn't find one. The version below was generated by
> chatgpt, which looks plausibly correct to me.
> 
> -Peff
> 
> diff --git a/strbuf.c b/strbuf.c
> index 9731ecdc1f..c26614a698 100644
> --- a/strbuf.c
> +++ b/strbuf.c
> @@ -361,16 +361,52 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
>  	va_end(ap);
>  }
>  
> +static const uint64_t powers_of_10[] = {
> +    1ULL,
> +    10ULL,
> +    100ULL,
> +    1000ULL,
> +    10000ULL,
> +    100000ULL,
> +    1000000ULL,
> +    10000000ULL,
> +    100000000ULL,
> +    1000000000ULL,
> +    10000000000ULL,
> +    100000000000ULL,
> +    1000000000000ULL,
> +    10000000000000ULL,
> +    100000000000000ULL,
> +    1000000000000000ULL,
> +    10000000000000000ULL,
> +    100000000000000000ULL,
> +    1000000000000000000ULL,
> +    10000000000000000000ULL,
> +};
> +
> +unsigned decimal_length_u64(uint64_t n)
> +{
> +    if (n == 0)
> +        return 1;
> +
> +    unsigned b = 63 - __builtin_clzll(n);
> +    /* approximate floor(log10(n)) */
> +    unsigned t = (b * 1233) >> 12;
> +    /* correct if estimate was low */
> +    return t + 1 + (n >= powers_of_10[t + 1]);
> +}

Clever.  But it seems for smallish object size numbers at least dividing
by ten repeatedly is not causing a bottleneck.

René


  parent reply	other threads:[~2026-05-13 17:46 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-12 11:55 [PATCH 0/4] strbuf: add and use strbuf_add_uint() René Scharfe
2026-05-12 11:56 ` [PATCH 1/4] strbuf: add strbuf_add_uint() René Scharfe
2026-05-12 18:42   ` Jeff King
2026-05-12 19:32     ` René Scharfe
2026-05-13 16:22       ` Jeff King
2026-05-13 16:47         ` Jeff King
2026-05-13 16:49         ` Jeff King
2026-05-14 11:09           ` René Scharfe
2026-05-14 11:53             ` Junio C Hamano
2026-05-15  3:53             ` Jeff King
2026-05-13 17:46         ` René Scharfe [this message]
2026-05-12 11:56 ` [PATCH 2/4] cat-file: use strbuf_add_uint() René Scharfe
2026-05-12 18:46   ` Jeff King
2026-05-12 11:56 ` [PATCH 3/4] ls-files: " René Scharfe
2026-05-12 19:01   ` Jeff King
2026-05-12 20:44     ` René Scharfe
2026-05-13 16:46       ` Jeff King
2026-05-12 11:56 ` [PATCH 4/4] ls-tree: " René Scharfe

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9e0b4f9f-ffcb-4dad-bd4f-295bbc011a1e@web.de \
    --to=l.s.r@web.de \
    --cc=git@vger.kernel.org \
    --cc=peff@peff.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox