git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v3] packed-refs: use `fwrite()` when passing refs verbatim

From
Patrick Steinhardt <ps@pks.im>
Date
Oct 6, 2026, 12:31 UTC
Message-ID
<asTqPcCl3RdS8YN4@pks.im>
In-Reply-To
<20261006-kn-speedup-packed-refs-v3-1-a1c76b1df9e0@gmail.com>
On Tue, Oct 06, 2026 at 11:18:40AM +0200, Karthik Nayak wrote:
Show 10 quoted lines
> 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()`.

Nit, not worth a reroll on its own: you state the status quo and then jump to the solution right away without stating what the problem is with the status quo.

Show 13 quoted lines
> 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 way this is written makes you think that `pos == record_start`, and thus one wonders why we even need this separate variable in the first place. So I assume that we modify `pos` in some cases without modifying the new variable at the same point in time. But if so, the above comment is not true anymore.

Show 16 quoted lines
> @@ -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;
> +}
Nit: this function is somewhat ponitless as it's a trivial wrapper
around fwrite(3).
Show 10 quoted lines
> @@ -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;

Alright, so `pos` and `record_start` do get advanced independent from one another. So the comment that you have for `record_start` is inaccurate indeed.

> +			if (write_packed_entry_raw(out,
> +						   packed_iter->record_start,
> +						   len))
>  				goto write_error;

Other than those nits though I'm quite happy about this change. A 20% win is nothing to scoff at, doubly so because reference deletions are extremely expensive once your repository reaches a certain number of refs.

Thanks!
Patrick
Previous: Karthik NayakNext: Karthik Nayak
Message 8 of 16 in “packed-refs: use `fwrite()` when passing refs verbatim”
  1. packed-refs: use `fwrite()` when passing refs verbatimKarthik Nayak, Sep 30, 2026
  2. Toon ClaesOct 1, 2026
  3. Karthik NayakOct 2, 2026
  4. packed-refs: use `fwrite()` when passing refs verbatimKarthik Nayak, Oct 2, 2026
  5. Toon ClaesOct 5, 2026
  6. Karthik NayakOct 6, 2026
  7. packed-refs: use `fwrite()` when passing refs verbatimKarthik Nayak, Oct 6, 2026
  8. Patrick SteinhardtOct 6, 2026
  9. Karthik NayakOct 6, 2026
  10. Patrick SteinhardtOct 7, 2026
  11. Karthik NayakOct 7, 2026
  12. Junio C HamanoOct 6, 2026
  13. Karthik NayakOct 6, 2026
  14. packed-refs: use `fwrite()` when passing refs verbatimKarthik Nayak, Oct 7, 2026
  15. Patrick SteinhardtOct 7, 2026
  16. Toon ClaesOct 8, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.