[PATCH v2] packed-refs: use `fwrite()` when passing refs verbatim
- From
Karthik Nayak <karthik.188@gmail.com>
- Date
- Oct 2, 2026, 13:03 UTC
- Message-ID
- <20261002-kn-speedup-packed-refs-v2-1-2ae75772ebc1@gmail.com>
- In-Reply-To
- <20260930-kn-speedup-packed-refs-v1-1-111cd03d9b0e@gmail.com>
The `write_with_updates()` function uses a `struct ref_iterator` to iterate over all refs to write to the temporary packed-refs file. It receives the iterator from `packed_ref_iterator_begin()` which takes a snapshot of the 'packed-refs' file.
While writing to the new packed-refs file, writes are routed via `write_packed_entry()` which uses `fprintf()`. Even for references which haven't changed, we use the same mechanism. Instead, let's track the position of unchanged references in the snapshot iterator and directly use `fwrite()`.
With this, any sanitation which was happening as a side of reformatting is now lost. But that was never the job of this section of the code, since the main intention is to simply rewrite the remaining refs post deletion of the selective few.
This removes the unnecessary formatting operation involved. We can see a consistent ~20% performance improvement when deleting from packed references.
Benchmark 1: update-ref: delete ref (refcount = 100000, revision = master) Time (mean ± σ): 28.7 ms ± 1.7 ms [User: 22.5 ms, System: 5.9 ms] Range (min … max): 26.7 ms … 33.3 ms 46 runs
Benchmark 2: update-ref: delete ref (refcount = 100000, revision = b4/kn-speedup-packed-refs) Time (mean ± σ): 23.8 ms ± 1.2 ms [User: 17.5 ms, System: 6.0 ms] Range (min … max): 22.1 ms … 27.7 ms 56 runs
Summary
update-ref: delete ref (refcount = 100000, revision = b4/kn-speedup-packed-refs) ran
1.21 ± 0.09 times faster than update-ref: delete ref (refformat = files, refcount = 100000, revision = master)Signed-off-by: Karthik Nayak <karthik.188@gmail.com> --- Changes in v2: - Instead of using the existing function, introduce a new `write_packed_entry_raw()`. - Modify the commit to also note that we lose sanitization. - Link to v1: https://patch.msgid.link/20260930-kn-speedup-packed-refs-v1-1-111cd03d9b0e@gmail.com --- refs/packed-backend.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-)
diff --git a/refs/packed-backend.c b/refs/packed-backend.c index a73fc6aca7..43ad674cf4 100644 --- a/refs/packed-backend.c +++ b/refs/packed-backend.c @@ -879,6 +879,12 @@ struct packed_ref_iterator { /* The current position in the snapshot's buffer: */ const char *pos; + /* + * Start of the current record, set when advancing `pos`. Used to + * pass records verbatim to `fwrite()`. + */ + const char *record_start; + /* The end of the part of the buffer that will be iterated over: */ const char *eof; @@ -933,6 +939,7 @@ static int next_record(struct packed_ref_iterator *iter) if (iter->pos == iter->eof) return ITER_DONE; + iter->record_start = iter->pos; iter->base.ref.flags = REF_ISPACKED; p = iter->pos; @@ -1233,6 +1240,19 @@ static int write_packed_entry(FILE *fh, const char *refname, return 0; } +/* + * Write an entry to the packed-refs file skip any formatting and directly + * write to the file using `fwrite()`. e.g. when deleting references and + * remaining refs need to be written verbatim. + */ +static int write_packed_entry_raw(FILE *fh, const char *entry, size_t len) +{ + if (fwrite(entry, len, 1, fh) != 1) + return -1; + + return 0; +} + int packed_refs_lock(struct ref_store *ref_store, int flags, struct strbuf *err) { struct packed_ref_store *refs = @@ -1530,9 +1550,13 @@ static enum ref_transaction_error write_with_updates(struct packed_ref_store *re } if (cmp < 0) { - /* Pass the old reference through. */ - if (write_packed_entry(out, iter->ref.name, - iter->ref.oid, iter->ref.peeled_oid)) + const struct packed_ref_iterator *packed_iter = + (const struct packed_ref_iterator *)iter; + size_t len = packed_iter->pos - packed_iter->record_start; + + if (write_packed_entry_raw(out, + packed_iter->record_start, + len)) goto write_error; if ((ok = ref_iterator_advance(iter)) != ITER_OK) { --- base-commit: a018953688f1b10bddf91bff8747068f5f4746a4 change-id: 20260930-kn-speedup-packed-refs-9868f5d0abe9 Thanks - Karthik