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

Re: [PATCH v4 00/13] Serialized Git Commit Graph

From
Derrick Stolee <stolee@gmail.com>
Date
Apr 2, 2018, 13:02 UTC
Message-ID
<f5d8934e-afc2-39d4-b7d5-e5ba5e5021a1@gmail.com>
In-Reply-To
<867eptkeeq.fsf@gmail.com>
On 3/30/2018 7:10 AM, Jakub Narebski wrote:
> I hope that I am addressing the most recent version of this series.
Hi Jakub. Thanks for the interest in this patch series.

The most-recent version is v6 [1], but I will re-roll to v7 soon (after v2.17.0 is marked).

[1] https://public-inbox.org/git/20180314192736.70602-1-dstolee@microsoft.com/T/#u

Show 33 quoted lines
> Derrick Stolee <stolee@gmail.com> writes:
>
>> As promised [1], this patch contains a way to serialize the commit graph.
>> The current implementation defines a new file format to store the graph
>> structure (parent relationships) and basic commit metadata (commit date,
>> root tree OID) in order to prevent parsing raw commits while performing
>> basic graph walks. For example, we do not need to parse the full commit
>> when performing these walks:
>>
>> * 'git log --topo-order -1000' walks all reachable commits to avoid
>>    incorrect topological orders, but only needs the commit message for
>>    the top 1000 commits.
>>
>> * 'git merge-base <A> <B>' may walk many commits to find the correct
>>    boundary between the commits reachable from A and those reachable
>>    from B. No commit messages are needed.
>>
>> * 'git branch -vv' checks ahead/behind status for all local branches
>>    compared to their upstream remote branches. This is essentially as
>>    hard as computing merge bases for each.
>>
>> The current patch speeds up these calculations by injecting a check in
>> parse_commit_gently() to check if there is a graph file and using that
>> to provide the required metadata to the struct commit.
> That's nice.
>
> What are the assumptions about the serialized commit graph format? Does
> it need to be:
>   - extensible without rewriting (e.g. append-only)?
>   - like the above, but may need rewriting for optimal performance?
>   - extending it needs to rewrite whole file?
>
> Excuse me if it waas already asked and answered.

It is not extensible without rewriting. Reducing write time was not a main goal, since the graph will be written only occasionally during data management phases (like 'gc' or 'repack'; this integration is not implemented yet).

Show 17 quoted lines
>
>> The file format has room to store generation numbers, which will be
>> provided as a patch after this framework is merged. Generation numbers
>> are referenced by the design document but not implemented in order to
>> make the current patch focus on the graph construction process. Once
>> that is stable, it will be easier to add generation numbers and make
>> graph walks aware of generation numbers one-by-one.
> As the serialized commit graph format is versioned, I wonder if it would
> be possible to speed up graph walks even more by adding to it FELINE
> index (pair of numbers) from "Reachability Queries in Very Large Graphs:
> A Fast Refined Olnine Search Approach" (2014) - available at
> http://openproceedings.org/EDBT/2014/paper_166.pdf
>
> The implementation would probably need adjustments to make it
> unambiguous and unambiguously extensible; unless there is place for
> indices that are local-only and need to be recalculated from scratch
> when graph changes (to cover all graph).

The chunk-based format is intended to allow extra indexes like the one you recommend, without needing to increase the version number. Using an optional chunk allows older versions of Git to read the file without error, since the data is "extra", and newer versions can take advantage of the acceleration.

At one point, I was investigating these reachability indexes (I read "SCARAB: Scaling Reachability Computation on Large Graphs" by Jihn, Ruan, Dey, and Xu [2]) but find the question that these indexes target to be lacking for most of the Git uses. That is, they ask the boolean question "Can X reach Y?". More often, Git needs to answer "What is the set of commits reachable from X but not from Y" or "Topologically sort commits reachable from X" or "How many commits are in each part of the symmetric difference between reachable from X or reachable from Y?"

The case for "Can X reach Y?" is mostly for commands like 'git branch --contains', when 'git fetch' checks for forced-updates of branches, or when the server decides enough negotiation has occurred during a 'git fetch'. While these may be worth investigating, they also benefit greatly from the accelerated graph walk introduced in the current format.

I would be happy to review any effort to extend the commit-graph format to include such indexes, as long as the performance benefits outweigh the complexity to create them.

[2] http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.719.8396&rep=rep1&type=pdf

Show 12 quoted lines
>
>> Here are some performance results for a copy of the Linux repository
>> where 'master' has 704,766 reachable commits and is behind 'origin/master'
>> by 19,610 commits.
>>
>> | Command                          | Before | After  | Rel % |
>> |----------------------------------|--------|--------|-------|
>> | log --oneline --topo-order -1000 |  5.9s  |  0.7s  | -88%  |
>> | branch -vv                       |  0.42s |  0.27s | -35%  |
>> | rev-list --all                   |  6.4s  |  1.0s  | -84%  |
>> | rev-list --all --objects         | 32.6s  | 27.6s  | -15%  |
> That's the "Rel %" of "Before", that is delta/before, isn't it?
I do mean the relative change.
Show 15 quoted lines
>
>> To test this yourself, run the following on your repo:
>>
>>    git config core.commitGraph true
>>    git show-ref -s | git commit-graph write --set-latest --stdin-commits
>>
>> The second command writes a commit graph file containing every commit
>> reachable from your refs. Now, all git commands that walk commits will
>> check your graph first before consulting the ODB. You can run your own
>> performance comparisions by toggling the 'core.commitgraph' setting.
> Good.  It is nicely similar to how bitmap indices (of reachability) are
> handled.
>
> I just wonder what happens in the (rare) presence of grafts (old
> mechanism), or "git replace"-d commits...

In the design document, I mention that the current implementation does not work with grafts (it will ignore them). A later patch will refactor the graft code so we can access it from the commit-graph parsing of a commit without copy-pasting the code out of parse_commit_gently().

The commit-graph is only a compact representation of the object database. If a commit is replaced with 'git replace' before 'git commit-graph write' then the commit-graph write will write the replaced object. I haven't tested what happens when a commit-graph is written and then a commit is replaced, but my guess is that the replacement does not occur until a full parse is attempted (i.e. when reading author or commit message information). This will lead to unknown results.

Thanks for pointing out the interaction with 'git replace'. I have items to fix grafts and replaced commits before integrating commit-graph writes into automatic actions like 'gc.auto'.

Thanks, -Stolee

Previous: Jakub NarebskiNext: Jakub Narebski
Message 140 of 146 in “Serialized Git Commit Graph”
  1. 00/14 Serialized Git Commit GraphDerrick Stolee, Jan 30, 2018
  2. 01/14 commit-graph: add format documentDerrick Stolee, Jan 30, 2018
  3. Jonathan TanFeb 1, 2018
  4. 03/14 commit-graph: create git-commit-graph builtinDerrick Stolee, Jan 30, 2018
  5. SZEDER GáborFeb 2, 2018
  6. 06/14 commit-graph: implement git-commit-graph --readDerrick Stolee, Jan 30, 2018
  7. Stefan BellerJan 31, 2018
  8. SZEDER GáborFeb 2, 2018
  9. Jonathan TanFeb 2, 2018
  10. Derrick StoleeFeb 5, 2018
  11. 08/14 commit-graph: implement git-commit-graph --clearDerrick Stolee, Jan 30, 2018
  12. SZEDER GáborFeb 2, 2018
  13. 11/14 commit: integrate commit graph with commit parsingDerrick Stolee, Jan 30, 2018
  14. Jonathan TanFeb 2, 2018
  15. Derrick StoleeFeb 6, 2018
  16. 13/14 commit-graph: close under reachabilityDerrick Stolee, Jan 30, 2018
  17. 09/14 commit-graph: teach git-commit-graph --delete-expiredDerrick Stolee, Jan 30, 2018
  18. SZEDER GáborFeb 2, 2018
  19. 12/14 commit-graph: read only from specific pack-indexesDerrick Stolee, Jan 30, 2018
  20. 14/14 commit-graph: build graph from starting commitsDerrick Stolee, Jan 30, 2018
  21. 10/14 commit-graph: add core.commitgraph settingDerrick Stolee, Jan 30, 2018
  22. Igor DjordjevicJan 31, 2018
  23. SZEDER GáborFeb 2, 2018
  24. 02/14 graph: add commit graph design documentDerrick Stolee, Jan 30, 2018
  25. Stefan BellerJan 31, 2018
  26. 05/14 commit-graph: implement git-commit-graph --writeDerrick Stolee, Jan 30, 2018
  27. Jonathan TanFeb 1, 2018
  28. Stefan BellerFeb 2, 2018
  29. Junio C HamanoFeb 2, 2018
  30. Derrick StoleeFeb 3, 2018
  31. Jeff KingFeb 3, 2018
  32. Junio C HamanoFeb 5, 2018
  33. Derrick StoleeFeb 6, 2018
  34. SZEDER GáborFeb 1, 2018
  35. Derrick StoleeFeb 5, 2018
  36. SZEDER GáborFeb 2, 2018
  37. 07/14 commit-graph: implement git-commit-graph --update-headDerrick Stolee, Jan 30, 2018
  38. SZEDER GáborFeb 2, 2018
  39. Derrick StoleeFeb 5, 2018
  40. SZEDER GáborFeb 2, 2018
  41. 04/14 commit-graph: implement construct_commit_graph()Derrick Stolee, Jan 30, 2018
  42. Jonathan TanFeb 1, 2018
  43. SZEDER GáborFeb 1, 2018
  44. SZEDER GáborFeb 2, 2018
  45. Derrick StoleeFeb 5, 2018
  46. SZEDER GáborFeb 7, 2018
  47. Derrick StoleeFeb 7, 2018
  48. Stefan BellerJan 30, 2018
  49. Stefan BellerFeb 1, 2018
  50. 00/14 Serialized Git Commit GraphDerrick Stolee, Feb 8, 2018
  51. 01/14 commit-graph: add format documentDerrick Stolee, Feb 8, 2018
  52. Junio C HamanoFeb 8, 2018
  53. Derrick StoleeFeb 8, 2018
  54. Junio C HamanoFeb 8, 2018
  55. 03/14 commit-graph: create git-commit-graph builtinDerrick Stolee, Feb 8, 2018
  56. Junio C HamanoFeb 8, 2018
  57. Derrick StoleeFeb 8, 2018
  58. Junio C HamanoFeb 8, 2018
  59. 07/14 commit-graph: update graph-head during writeDerrick Stolee, Feb 8, 2018
  60. Junio C HamanoFeb 12, 2018
  61. Junio C HamanoFeb 12, 2018
  62. Derrick StoleeFeb 12, 2018
  63. Jonathan TanFeb 13, 2018
  64. 10/14 commit-graph: add core.commitGraph settingDerrick Stolee, Feb 8, 2018
  65. 12/14 commit-graph: close under reachabilityDerrick Stolee, Feb 8, 2018
  66. 11/14 commit: integrate commit graph with commit parsingDerrick Stolee, Feb 8, 2018
  67. Jonathan TanFeb 14, 2018
  68. Derrick StoleeFeb 14, 2018
  69. Junio C HamanoFeb 15, 2018
  70. 05/14 commit-graph: implement 'git-commit-graph write'Derrick Stolee, Feb 8, 2018
  71. Jonathan TanFeb 13, 2018
  72. 08/14 commit-graph: implement 'git-commit-graph clear'Derrick Stolee, Feb 8, 2018
  73. Jonathan TanFeb 13, 2018
  74. 09/14 commit-graph: implement --delete-expiredDerrick Stolee, Feb 8, 2018
  75. 13/14 commit-graph: read only from specific pack-indexesDerrick Stolee, Feb 8, 2018
  76. 14/14 commit-graph: build graph from starting commitsDerrick Stolee, Feb 8, 2018
  77. SZEDER GáborFeb 9, 2018
  78. Derrick StoleeFeb 9, 2018
  79. 06/14 commit-graph: implement 'git-commit-graph read'Derrick Stolee, Feb 8, 2018
  80. Junio C HamanoFeb 8, 2018
  81. 02/14 graph: add commit graph design documentDerrick Stolee, Feb 8, 2018
  82. 04/14 commit-graph: implement write_commit_graph()Derrick Stolee, Feb 8, 2018
  83. Junio C HamanoFeb 8, 2018
  84. Junio C HamanoFeb 15, 2018
  85. Derrick StoleeFeb 15, 2018
  86. Derrick StoleeFeb 14, 2018
  87. Stefan BellerFeb 14, 2018
  88. Derrick StoleeFeb 14, 2018
  89. 00/13 Serialized Git Commit GraphDerrick Stolee, Feb 19, 2018
  90. 01/13 commit-graph: add format documentDerrick Stolee, Feb 19, 2018
  91. Junio C HamanoFeb 20, 2018
  92. Stefan BellerFeb 21, 2018
  93. Derrick StoleeFeb 21, 2018
  94. Stefan BellerFeb 21, 2018
  95. Jakub NarebskiMar 30, 2018
  96. Derrick StoleeApr 2, 2018
  97. Jakub NarebskiApr 2, 2018
  98. 03/13 commit-graph: create git-commit-graph builtinDerrick Stolee, Feb 19, 2018
  99. Junio C HamanoFeb 20, 2018
  100. Junio C HamanoFeb 21, 2018
  101. Derrick StoleeFeb 23, 2018
  102. SZEDER GáborFeb 26, 2018
  103. Derrick StoleeFeb 26, 2018
  104. 06/13 commit-graph: implement git commit-graph readDerrick Stolee, Feb 19, 2018
  105. Junio C HamanoFeb 21, 2018
  106. Junio C HamanoFeb 22, 2018
  107. 08/13 commit-graph: implement --delete-expiredDerrick Stolee, Feb 19, 2018
  108. Stefan BellerFeb 21, 2018
  109. Derrick StoleeFeb 23, 2018
  110. Junio C HamanoFeb 22, 2018
  111. Derrick StoleeFeb 23, 2018
  112. Junio C HamanoFeb 23, 2018
  113. Derrick StoleeFeb 23, 2018
  114. Junio C HamanoFeb 23, 2018
  115. 09/13 commit-graph: add core.commitGraph settingDerrick Stolee, Feb 19, 2018
  116. 10/13 commit-graph: close under reachabilityDerrick Stolee, Feb 19, 2018
  117. 11/13 commit: integrate commit graph with commit parsingDerrick Stolee, Feb 19, 2018
  118. 12/13 commit-graph: read only from specific pack-indexesDerrick Stolee, Feb 19, 2018
  119. Stefan BellerFeb 21, 2018
  120. Derrick StoleeFeb 23, 2018
  121. 13/13 commit-graph: build graph from starting commitsDerrick Stolee, Feb 19, 2018
  122. 07/13 commit-graph: implement --set-latestDerrick Stolee, Feb 19, 2018
  123. Junio C HamanoFeb 22, 2018
  124. Derrick StoleeFeb 23, 2018
  125. 02/13 graph: add commit graph design documentDerrick Stolee, Feb 19, 2018
  126. Junio C HamanoFeb 20, 2018
  127. Derrick StoleeFeb 23, 2018
  128. Stefan BellerFeb 21, 2018
  129. 04/13 commit-graph: implement write_commit_graph()Derrick Stolee, Feb 19, 2018
  130. Junio C HamanoFeb 20, 2018
  131. Derrick StoleeFeb 23, 2018
  132. Junio C HamanoFeb 23, 2018
  133. Junio C HamanoFeb 23, 2018
  134. Derrick StoleeFeb 23, 2018
  135. SZEDER GáborFeb 26, 2018
  136. Junio C HamanoFeb 28, 2018
  137. 05/13 commit-graph: implement 'git-commit-graph write'Derrick Stolee, Feb 19, 2018
  138. Junio C HamanoFeb 21, 2018
  139. Jakub NarebskiMar 30, 2018
  140. Derrick StoleeApr 2, 2018
  141. Jakub NarebskiApr 2, 2018
  142. Derrick StoleeApr 2, 2018
  143. Stefan BellerApr 2, 2018
  144. Derrick StoleeApr 2, 2018
  145. Stefan BellerApr 2, 2018
  146. Jakub NarebskiApr 7, 2018

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.