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

Re: [PATCH 0/6] PATH WALK I: The path-walk API

From
Jeff King <peff@peff.net>
Date
Nov 4, 2024, 17:25 UTC
Message-ID
<20241104172533.GA2985568@coredump.intra.peff.net>
In-Reply-To
<2d2940ef-0b26-4060-90b6-9b6969f23754@gmail.com>
On Mon, Nov 04, 2024 at 10:48:49AM -0500, Derrick Stolee wrote:
Show 9 quoted lines
> > I was discussing this a bit off-list with Peff (who I hope will join the
> > thread and share his own thoughts), but I wonder if it was a mistake to
> > discard your '--full-name-hash' idea (or something similar, which I'll
> > discuss in a bit below) from earlier.
> 
> I'd be happy to resurrect that series, adding in the learnings from
> working on the path-walk feature. It helps that the current series adds
> the path-walk API and has no conflicting changes in the pack-objects or
> repack builtins. (I can handle those conflicts as things merge down.)
Adding my two cents, the discussion we had came after reading this post:
  https://www.jonathancreamer.com/how-we-shrunk-our-git-repo-size-by-94-percent/

I think a few of the low-level details in there are confusing, but it seemed to me that most of the improvement he mentions is just about finding better delta candidates. And it seems obvious that our current pack_name_hash() is pretty rudimentary as context-sensitive hashing goes and won't do well for long paths with similar endings.

So just swapping that out for something better seems like an easy thing to do regardless of whether we pursue --path-walk. It doesn't drastically change how we choose delta pairs so it's not much code and it shouldn't conflict with other features. And the risk of making anything worse should be pretty low.

I wouldn't at all be surprised if --path-walk can do better, but if we do the easy thing first then I think it gives us a better idea of the cost/benefit it's providing.

I suspect there's room for both in the long run. You seem to be focused on push size and cost, whereas I think Taylor and I are more interested in overall repo size and cost of serving bitmapped fetches.

Show 9 quoted lines
> When the optimization idea is to focus on the full path and not care
> about the "locality" of the path name by its later bits, storing the
> full name in a list and storing an index into that list would have a
> very similar effect.
> 
> I'd be interested to explore the idea of storing the full path name.
> Based on my exploration with the 'test-tool name-hash' test helper in
> that series, I'm not sure that we will make significant gains by doing
> so. Worth trying.

The way I look at it is a possible continuum. We want to use pathnames as a way to sort delta candidates near each other, since we expect them to have high locality with respect to delta-able contents. The current name_hash uses a very small bit of that path information and throws away most of it. The other extreme end is holding the whole path. We may want to end up in the middle for two reasons:

  1. Dealing with whole paths might be costly (though I'm not yet
     convinced of that; outside of pathological cases, the number of
     paths in a repo tends to pale in comparison to the number of
     objects, and the per-object costs dominate during repacking).
  2. It's possible that over-emphasizing the path might be a slightly
     worse heuristic (and I think this is a potential danger of
     --path-walk, too). We still want to find candidate pairs that were
     copied or renamed, for example, or that substantially share content
     found in different parts of the tree.

So it would be interesting to be able to see the performance of various points on that line, from full path down to partial paths down to longer hashes down to the current hash. The true extreme end of course is no path info at all, but I think we know that sucks; that's why we implemented the bitmap name-hash extension in the first place.

Show 5 quoted lines
> I don't know too much about SimHash or MinHash, but based on what I
> could gather from some initial reading I'm not sure that they would be
> effective without increasing the hash length. We'd also get a different
> kind of locality, such as the appearance of a common word would be more
> likely to affect the locality than the end of the path.

Good point. This is all heuristics, of course, but I suspect that the order of the path is important, and that foo/bar.c and bar/foo.c are unlikely to be good matches.

Show 12 quoted lines
> > I realize that this is taking us back to an idea you've already
> > presented to the list, but I think (to me, at least) the benefit and
> > simplicity of that approach has only become clear to me in hindsight
> > when seeing some alternatives. I would like to apologize for the time
> > you spent reworking this series back and forth to have the response be
> > "maybe we should have just done the first thing you suggested". Like I
> > said, I think to me it was really only clear in hindsight.
> 
> I always assumed that we'd come back to it eventually. There is also the
> extra bit about making the change to the name-hash compatible with the
> way name-hashes are stored in the reachability bitmaps. That will need
> some work before it is ready for prime time.

Having worked on that feature of bitmaps, I'm not too worried about it. I think we'd just need to:

  - introduce a new bitmap ext with a flag (HASH_CACHE_V2 or something,
    either with the new hash, or with a "version" byte at the start for
    extensibility).
  - when bitmaps are not in use, we're free to use whichever hash we
    want internally. If the new hash is consistently better, we'd
    probably just enable it by default.
  - when packing using on-disk bitmaps, use internally whichever format
    the on-disk file provided. Technically the format could even provide
    both (in which case we'd prefer the new hash), but I don't see much
    point.
  - when writing bitmaps, use whichever hash the command-line options
    asked for. There's an off chance somebody might want to generate a
    .bitmap file whose hashes will be understood by an older version of
    git, in which case they'd use --no-full-name-hash or whatever while
    repacking.

If we're considering full paths, then that is potentially a bit more involved, just because we'd want the format to avoid repeating duplicate paths for each object (plus they're no longer fixed-size). So probably an extension with packed NUL-terminated path strings, plus a set of fixed-length offsets into that block, one per object.

Show 7 quoted lines
> I disagree that all environments will prefer the --full-name-hash. I'm
> currently repeating the performance tests right now, and I've added one.
> The issues are:
> 
>  1. The --full-name-hash approach sometimes leads to a larger pack when
>     using "git push" on the client, especially when the name-hash is
>     already effective for compressing across paths.

That's interesting. I wonder which cases get worse, and if a larger window size might help. I.e., presumably we are pushing the candidates further away in the sorted delta list.

Show 6 quoted lines
>  2. A depth 1 shallow clone cannot use previous versions of a path, so
>     those situations will want to use the normal name hash. This can be
>     accomplished simply by disabling the --full-name-hash option when
>     the --shallow option is present; a more detailed version could be
>     used to check for a large depth before disabling it. This case also
>     disables bitmaps, so that isn't something to worry about.

I'm not sure why a larger hash would be worse in a shallow clone. As you note, with only one version of each path the name-similarity heuristic is not likely to buy you much. But I'd have thought that would be true for the existing name hash as well as a longer one. Maybe this is the "over-emphasizing" case.

-Peff
Previous: Derrick StoleeNext: Junio C Hamano
Message 22 of 67 in “PATH WALK I: The path-walk API”
  1. 0/6 PATH WALK I: The path-walk APIDerrick Stolee via GitGitGadget, Oct 31, 2024
  2. 1/6 path-walk: introduce an object walk by pathDerrick Stolee via GitGitGadget, Oct 31, 2024
  3. karthik nayakNov 1, 2024
  4. Derrick StoleeNov 1, 2024
  5. 2/6 test-lib-functions: add test_cmp_sortedDerrick Stolee via GitGitGadget, Oct 31, 2024
  6. 3/6 t6601: add helper for testing path-walk APIDerrick Stolee via GitGitGadget, Oct 31, 2024
  7. karthik nayakNov 1, 2024
  8. Jonathan TanNov 1, 2024
  9. Derrick StoleeNov 4, 2024
  10. Jonathan TanNov 4, 2024
  11. Derrick StoleeNov 8, 2024
  12. Patrick SteinhardtNov 6, 2024
  13. Derrick StoleeNov 8, 2024
  14. 4/6 path-walk: allow consumer to specify object typesDerrick Stolee via GitGitGadget, Oct 31, 2024
  15. 5/6 path-walk: visit tags and cached objectsDerrick Stolee via GitGitGadget, Oct 31, 2024
  16. karthik nayakNov 1, 2024
  17. Derrick StoleeNov 4, 2024
  18. 6/6 path-walk: mark trees and blobs as UNINTERESTINGDerrick Stolee via GitGitGadget, Oct 31, 2024
  19. Derrick StoleeOct 31, 2024
  20. Taylor BlauNov 1, 2024
  21. Derrick StoleeNov 4, 2024
  22. Jeff KingNov 4, 2024
  23. Junio C HamanoNov 5, 2024
  24. Derrick StoleeNov 8, 2024
  25. Junio C HamanoNov 11, 2024
  26. Derrick StoleeNov 11, 2024
  27. Jeff KingNov 11, 2024
  28. Junio C HamanoNov 11, 2024
  29. Jeff KingNov 11, 2024
  30. 0/6 PATH WALK I: The path-walk APIDerrick Stolee via GitGitGadget, Nov 9, 2024
  31. 1/6 path-walk: introduce an object walk by pathDerrick Stolee via GitGitGadget, Nov 9, 2024
  32. 2/6 test-lib-functions: add test_cmp_sortedDerrick Stolee via GitGitGadget, Nov 9, 2024
  33. 3/6 t6601: add helper for testing path-walk APIDerrick Stolee via GitGitGadget, Nov 9, 2024
  34. Taylor BlauNov 21, 2024
  35. 4/6 path-walk: allow consumer to specify object typesDerrick Stolee via GitGitGadget, Nov 9, 2024
  36. Taylor BlauNov 21, 2024
  37. 5/6 path-walk: visit tags and cached objectsDerrick Stolee via GitGitGadget, Nov 9, 2024
  38. 6/6 path-walk: mark trees and blobs as UNINTERESTINGDerrick Stolee via GitGitGadget, Nov 9, 2024
  39. Taylor BlauNov 21, 2024
  40. Patrick SteinhardtNov 25, 2024
  41. Junio C HamanoNov 26, 2024
  42. Patrick SteinhardtNov 26, 2024
  43. Junio C HamanoNov 26, 2024
  44. 0/7 PATH WALK I: The path-walk APIDerrick Stolee via GitGitGadget, Dec 6, 2024
  45. 1/7 path-walk: introduce an object walk by pathDerrick Stolee via GitGitGadget, Dec 6, 2024
  46. Patrick SteinhardtDec 13, 2024
  47. Derrick StoleeDec 18, 2024
  48. Patrick SteinhardtDec 27, 2024
  49. 2/7 test-lib-functions: add test_cmp_sortedDerrick Stolee via GitGitGadget, Dec 6, 2024
  50. 3/7 t6601: add helper for testing path-walk APIDerrick Stolee via GitGitGadget, Dec 6, 2024
  51. 4/7 path-walk: allow consumer to specify object typesDerrick Stolee via GitGitGadget, Dec 6, 2024
  52. 5/7 path-walk: visit tags and cached objectsDerrick Stolee via GitGitGadget, Dec 6, 2024
  53. Patrick SteinhardtDec 13, 2024
  54. Derrick StoleeDec 18, 2024
  55. 6/7 path-walk: mark trees and blobs as UNINTERESTINGDerrick Stolee via GitGitGadget, Dec 6, 2024
  56. 7/7 path-walk: reorder object visitsDerrick Stolee via GitGitGadget, Dec 6, 2024
  57. Patrick SteinhardtDec 13, 2024
  58. 0/7 PATH WALK I: The path-walk APIDerrick Stolee via GitGitGadget, Dec 20, 2024
  59. 1/7 path-walk: introduce an object walk by pathDerrick Stolee via GitGitGadget, Dec 20, 2024
  60. Patrick SteinhardtDec 27, 2024
  61. 2/7 test-lib-functions: add test_cmp_sortedDerrick Stolee via GitGitGadget, Dec 20, 2024
  62. 3/7 t6601: add helper for testing path-walk APIDerrick Stolee via GitGitGadget, Dec 20, 2024
  63. 4/7 path-walk: allow consumer to specify object typesDerrick Stolee via GitGitGadget, Dec 20, 2024
  64. 5/7 path-walk: visit tags and cached objectsDerrick Stolee via GitGitGadget, Dec 20, 2024
  65. 6/7 path-walk: mark trees and blobs as UNINTERESTINGDerrick Stolee via GitGitGadget, Dec 20, 2024
  66. 7/7 path-walk: reorder object visitsDerrick Stolee via GitGitGadget, Dec 20, 2024
  67. karthik nayakNov 1, 2024

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.