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

Re: [PATCH 15/34] commit-graph-format.txt: document the modified path Bloom filter chunks

From
SZEDER Gábor <szeder.dev@gmail.com>
Date
Jun 2, 2020, 17:59 UTC
Message-ID
<20200602175949.GA2898@szeder.dev>
In-Reply-To
<20200529085038.26008-16-szeder.dev@gmail.com>
On Fri, May 29, 2020 at 10:50:19AM +0200, SZEDER Gábor wrote:
> Modified Path Bloom Filters
Show 10 quoted lines
> Each modified path Bloom filter consists of:
> 
>   - 4 bytes specifying the number of bits in the Bloom filter's bit
>     array.
> 
>     For practical purposes 32 bit is more than sufficient to store the
>     number of bits in the Bloom filter's array.  When using k = 7
>     hashes, i.e. 10 bits per path, then we could store over 400
>     million paths in a single Bloom filter; with k = 32 hashes we'd
>     use 46 bit per path, which is still over 93 million paths.
Show 5 quoted lines
> Alternatives considered
> -----------------------
> 
> Here are some alternatives that I've considered but discarded and
> ideas that I haven't (yet) followed through:
>   - Varints.  Using 4 bytes for the size of each Bloom filter in the
>     Modified Path Bloom Filters chunk is a lot more than necessary.
>     How much space can be saved by using varints?
Not that much, at least compared to the whole commit-graph file.

Since 63 bit modified path Bloom filters are embedded in the index entries, it's pointless to store smaller Bloom filters, so the size of non-embedded Bloom filters can be defined as

  nr_bits = 64 + decode_varint(...)

A one byte varint can encode values up to 127, while a two bytes varint can encode values up to 16511. So the max nr_bits is 191 and 16575, respectively, which means max 19 or 1657 paths with 7 hashes, i.e. 10 bits per path. The table below shows the percentage of commits with embedded modified path Bloom filters and commits with non-embedded Bloom filters with one byte and two bytes varints, and how much space is saved.

                    Percentage of commits   |
                    modifying <= N paths    |   varint   commit-graph
                  compared to first parent  | size diff    file size
                  <=6      <=19     <=1657  |  (bytes)     (ls -lh)
  ------------------------------------------+-------------------------------
  elasticsearch  18.32%   65.56%    99.79%  |   -90158       9.5M      -0.9%
  jdk            26.62%   70.46%    97.94%  |   -90262        16M      -0.6%
  webkit         38.42%   82.24%    99.92%  |  -298824        19M      -1.6%
  android-base   42.32%   88.02%    99.98%  |  -132327        30M      -0.5%
  llvm-project   53.60%   93.86%    99.99%  |  -344239        24M      -1.4%
  gecko-dev      54.54%   87.15%    99.87%  |  -625029        63M      -1.0%
  tensorflow     55.17%   90.76%    99.52%  |   -83758       9.0M      -0.9%
  rails          58.71%   95.13%    99.99%  |   -53153       6.0M      -0.9%
  rust           59.29%   88.03%    99.96%  |   -90677       8.2M      -1.1%
  glibc          61.59%   91.11%    99.96%  |   -38422       3.8M      -1.0%
  gcc            63.80%   95.39%    99.97%  |  -179463        18M      -1.0%
  go             65.31%   95.19%    99.99%  |   -39109       3.2M      -1.2%
  cmssw          67.58%   93.02%    99.91%  |  -154440        23M      -0.7%
  linux          72.79%   95.27%    99.78%  |  -527045        78M      -0.7%
  cpython        81.91%   97.78%   100.00%  |   -40678       7.8M      -0.5%
  git            90.28%   98.56%   100.00%  |   -13406       3.9M      -0.4%
  homebrew-cask  98.61%   99.58%    99.99%  |    -2992       6.6M      -0.1%
  homebrew-core  99.81%   99.93%   100.00%  |     -810        11M      -0.1%
>     How much is the runtime overhead of decoding those varints?

Not enough to be above noise level. ("a lot of paths", MurmurHash3, k = 7, enhanced double hashing, 32 bit uint arithmetic)

                                       |   Average time spent
                   Average runtime     |  loading and querying
                                       |      Bloom filters
                  uint32     varint    |   uint32     varint
  -------------------------------------+-----------------------------
  android-base    0.1456s   0.144172s  |  0.01550s   0.01571s    1.3%
  cmssw           0.0313s   0.032046s  |  0.00383s   0.00395s    3.1%
  cpython         0.0810s   0.081649s  |  0.00765s   0.00785s    2.6%
  elasticsearch   0.0136s   0.013899s  |  0.00246s   0.00258s    4.8%
  gcc             0.2114s   0.211080s  |  0.02259s   0.02261s      0%
  gecko-dev       0.4815s   0.474903s  |  0.06004s   0.06028s    0.3%
  git             0.0310s   0.031156s  |  0.00192s   0.00195s    1.5%
  glibc           0.0282s   0.029032s  |  0.00320s   0.00342s    6.8%
  go              0.0403s   0.039408s  |  0.00428s   0.00414s   -3.3%
  jdk             0.0068s   0.006666s  |  0.00117s   0.00113s   -3.5%
  linux           0.0873s   0.087438s  |  0.01109s   0.01133s    2.1%
  llvm-project    0.4135s   0.418390s  |  0.04716s   0.04834s    2.5%
  rails           0.0391s   0.038997s  |  0.00449s   0.00448s   -0.3%
  rust            0.0439s   0.044569s  |  0.00444s   0.00461s    3.8%
  tensorflow      0.0487s   0.049166s  |  0.00618s   0.00634s    2.5%
  webkit          0.2420s   0.241807s  |  0.03353s   0.03379s    0.7%
>     How can we ensure that varint decoding doesn't read past the end
>     of the mmapped memory region?

With a decode_varint() variant that takes the max number of bytes to read as an additional parameter, and returns 0 if the varint is too long.

Previous: SZEDER GáborNext: SZEDER Gábor
Message 22 of 43 in “An alternative modified path Bloom filters implementation”
  1. 00/34 An alternative modified path Bloom filters implementationSZEDER Gábor, May 29, 2020
  2. 01/34 tree-walk.c: don't match submodule entries for 'submod/anything'SZEDER Gábor, May 29, 2020
  3. 02/34 commit-graph: fix parsing the Chunk Lookup tableSZEDER Gábor, May 29, 2020
  4. 03/34 commit-graph-format.txt: all multi-byte numbers are in network byte orderSZEDER Gábor, May 29, 2020
  5. 04/34 commit-slab: add a function to deep free entries on the slabSZEDER Gábor, May 29, 2020
  6. Derrick StoleeJun 4, 2020
  7. SZEDER GáborJun 27, 2020
  8. Derrick StoleeJun 29, 2020
  9. 05/34 diff.h: drop diff_tree_oid() & friends' return valueSZEDER Gábor, May 29, 2020
  10. 07/34 commit-graph: simplify parse_commit_graph() #1SZEDER Gábor, May 29, 2020
  11. 06/34 commit-graph: clean up #includesSZEDER Gábor, May 29, 2020
  12. 09/34 commit-graph: simplify write_commit_graph_file() #1SZEDER Gábor, May 29, 2020
  13. 10/34 commit-graph: simplify write_commit_graph_file() #2SZEDER Gábor, May 29, 2020
  14. 08/34 commit-graph: simplify parse_commit_graph() #2SZEDER Gábor, May 29, 2020
  15. 11/34 commit-graph: allocate the 'struct chunk_info' array dinamicallySZEDER Gábor, May 29, 2020
  16. 12/34 commit-graph: unify the signatures of all write_graph_chunk_*() functionsSZEDER Gábor, May 29, 2020
  17. 13/34 commit-graph: simplify write_commit_graph_file() #3SZEDER Gábor, May 29, 2020
  18. 14/34 commit-graph: check chunk sizes after writingSZEDER Gábor, May 29, 2020
  19. 16/34 Add a generic and minimal Bloom filter implementationSZEDER Gábor, May 29, 2020
  20. 17/34 Import a streaming-capable Murmur3 hash function implementationSZEDER Gábor, May 29, 2020
  21. 15/34 commit-graph-format.txt: document the modified path Bloom filter chunksSZEDER Gábor, May 29, 2020
  22. SZEDER GáborJun 2, 2020
  23. 18/34 commit-graph: write "empty" Modified Path Bloom Filter Index chunkSZEDER Gábor, May 29, 2020
  24. 19/34 commit-graph: add commit slab for modified path Bloom filtersSZEDER Gábor, May 29, 2020
  25. 20/34 commit-graph: fill the Modified Path Bloom Filter Index chunkSZEDER Gábor, May 29, 2020
  26. 21/34 commit-graph: load and use the Modified Path Bloom Filter Index chunkSZEDER Gábor, May 29, 2020
  27. 27/34 commit-graph: load modified path Bloom filters for merge commitsSZEDER Gábor, May 29, 2020
  28. 28/34 commit-graph: write Modified Path Bloom Filter Merge Index chunkSZEDER Gábor, May 29, 2020
  29. 30/34 commit-graph: move write_commit_graph_reachable below write_commit_graphSZEDER Gábor, May 29, 2020
  30. 29/34 commit-graph: extract init and free write_commit_graph_contextSZEDER Gábor, May 29, 2020
  31. 31/34 t7007-show: make the first test compatible with the next patchSZEDER Gábor, May 29, 2020
  32. 26/34 commit-graph: deduplicate modified path Bloom filtersSZEDER Gábor, May 29, 2020
  33. 25/34 commit-graph: check embedded modified path Bloom filters with a maskSZEDER Gábor, May 29, 2020
  34. 24/34 commit-graph: check all leading directories in modified path Bloom filtersSZEDER Gábor, May 29, 2020
  35. 23/34 commit-graph: load and use the Modified Path Bloom Filters chunkSZEDER Gábor, May 29, 2020
  36. 22/34 commit-graph: write the Modified Path Bloom Filters chunkSZEDER Gábor, May 29, 2020
  37. 34/34 commit-graph: use modified path Bloom filters with wildcards, if possibleSZEDER Gábor, May 29, 2020
  38. 33/34 commit-graph: write modified path Bloom filters in "history order"SZEDER Gábor, May 29, 2020
  39. 32/34 PoC commit-graph: use revision walk machinery for '--reachable'SZEDER Gábor, May 29, 2020
  40. Derrick StoleeMay 29, 2020
  41. Johannes SchindelinMay 28, 2020
  42. Taylor BlauJun 1, 2020
  43. Junio C HamanoJun 2, 2020

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.