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

Re: [PATCH 5/5] sha1_file: don't re-scan pack directory for null sha1

From
Stefan Beller <sbeller@google.com>
Date
Nov 20, 2017, 20:47 UTC
Message-ID
<CAGZ79kZWJhZ-6-1MZiWK4O-uWJG+T5QU29a5fRnw6R26J4fuCA@mail.gmail.com>
In-Reply-To
<20171120203523.c3pt5qi43e24ttqq@sigill.intra.peff.net>
On Mon, Nov 20, 2017 at 12:35 PM, Jeff King <peff@peff.net> wrote:
Show 63 quoted lines
> In theory nobody should ever ask the low-level object code
> for a null sha1. It's used as a sentinel for "no such
> object" in lots of places, so leaking through to this level
> is a sign that the higher-level code is not being careful
> about its error-checking.  In practice, though, quite a few
> code paths seem to rely on the null sha1 lookup failing as a
> way to quietly propagate non-existence (e.g., by feeding it
> to lookup_commit_reference_gently(), which then returns
> NULL).
>
> When this happens, we do two inefficient things:
>
>   1. We actually search for the null sha1 in packs and in
>      the loose object directory.
>
>   2. When we fail to find it, we re-scan the pack directory
>      in case a simultaneous repack happened to move it from
>      loose to packed.
>
> It's debatable whether (1) is a good idea or not. The
> performance drop is at least linear in the number of
> lookups, so it's not too bad. And if by some 2^-160th chance
> somebody does have such an object, we probably ought to
> access it. On the other hand, enough code paths treat the
> null sha1 specially that the object probably isn't usable,
> anyway.
>
> Problem (2), on the other hand, is a pretty severe
> performance issue. If you have a large number of packs,
> rescanning the pack directory can be very expensive. And it
> only helps in the case that you have an object with the null
> sha1 _and_ somebody was simultaneously repacking it. The
> tradeoff is certainly a bad one there.
>
> In an ideal world, we'd simply fix all of the callers to
> notice the null sha1 and avoid passing it to us. But a
> simple experiment to catch this with a BUG() shows that
> there are a large number of code paths.
>
> In the meantime, let's address problem (2). That's the
> minimal fix we can do to make the performance problems go
> away. p5551 shows this off (when a fetched ref is new, the
> "old" sha1 is 0{40}, which ends up being passed for
> fast-forward checks, the status table abbreviations, etc):
>
>   Test            HEAD^             HEAD
>   --------------------------------------------------------
>   5551.4: fetch   5.51(5.03+0.48)   0.17(0.10+0.06) -96.9%
>
> We could address (1), too, but there's not much performance
> improvement left to make.
>
> Signed-off-by: Jeff King <peff@peff.net>
> ---
> This is the minimal fix that addresses the performance issues.
> I'd actually have no problem at all declaring that looking up a null
> sha1 is insane, and having the object-lookup routines simply return "no
> such object" without even doing the loose/pack lookup first.
>
> I'm also fine with going down the BUG() route and fixing the
> higher-level callers, but it's a big enough task (with little enough
> real-world impact) that I think it would be worth applying this in the
> meantime.

It would have a lot of impact in the future, when new developers are hindered mis-using the API. The (unwritten) series with introducing BUG() would help a lot in 'holding it right' and I would expect fewer performance regressions over time.

The patch is impressively small for such a performance gain. Personally I think (1) (which essentially means "making null sha1 work like a regular sha1") is quite an endeavor at this point in time for this code base.

As a tangent, a similar but solved problem in the diff code is how NUL in user data is treated in xdiff for example, as there we kept being careful since the beginning (though I think we don't have tests for it, so it might be broken)

Stefan
Previous: Jeff KingNext: Jeff King
Message 13 of 25 in “avoiding pointless pack-directory re-scans”
  1. 0/5 avoiding pointless pack-directory re-scansJeff King, Nov 20, 2017
  2. 1/5 p5550: factor our nonsense-pack creationJeff King, Nov 20, 2017
  3. Eric SunshineNov 20, 2017
  4. Jeff KingNov 21, 2017
  5. Stefan BellerNov 22, 2017
  6. Jeff KingNov 22, 2017
  7. Junio C HamanoNov 23, 2017
  8. Jeff KingNov 23, 2017
  9. 2/5 t/perf/lib-pack: use fast-import checkpoint to create packsJeff King, Nov 20, 2017
  10. 3/5 p5551: add a script to test fetch pack-dir rescansJeff King, Nov 20, 2017
  11. 4/5 everything_local: use "quick" object existence checkJeff King, Nov 20, 2017
  12. 5/5 sha1_file: don't re-scan pack directory for null sha1Jeff King, Nov 20, 2017
  13. Stefan BellerNov 20, 2017
  14. Jeff KingNov 20, 2017
  15. Junio C HamanoNov 21, 2017
  16. Jeff KingNov 21, 2017
  17. Junio C HamanoNov 22, 2017
  18. Jeff KingNov 22, 2017
  19. Junio C HamanoNov 23, 2017
  20. Jeff KingNov 24, 2017
  21. Junio C HamanoNov 25, 2017
  22. Junio C HamanoNov 21, 2017
  23. Jeff KingNov 21, 2017
  24. Junio C HamanoNov 22, 2017
  25. Jeff KingNov 22, 2017

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.