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

Re: [PATCH 0/7] pack-objects: Create an alternative name hash algorithm (recreated)

From
JTJonathan Tan <jonathantanmy@google.com>
Date
Nov 21, 2024, 23:50 UTC
Message-ID
<20241121235014.2554033-1-jonathantanmy@google.com>
In-Reply-To
<pull.1823.git.1730775907.gitgitgadget@gmail.com>
"Derrick Stolee via GitGitGadget" <gitgitgadget@gmail.com> writes:
> This series introduces a new name-hash algorithm, but does not replace the
> existing one. There are cases, such as packing a single snapshot of a
> repository, where the existing algorithm outperforms the new one.

I came up with a hash function that both uses information from a lot more of the path (not the full name, though) and preserves the sortable property (diff at the end of this email). It also contains fixes to the existing algorithm: not wasting the most significant bits of the hash if files in the repo mostly end in a lowercase alphabetic character, and the cast from a possibly-signed-possibly-unsigned char to a uint32_t.

The results look quite good. In summary, the pack sizes are comparable to Stolee's results in the case of fluentui, and better than Stolee's results in the case of git.

Here's one run on the fluentui repo (git clone https:// github.com/microsoft/fluentui; cd fluentui; git checkout a637a06df05360ce5ff21420803f64608226a875^ following the instructions in [1]:

(before my change)

Test this tree --------------------------------------------------------------------- 5313.2: thin pack 0.03(0.01+0.01) 5313.3: thin pack size 1.1K 5313.4: thin pack with --full-name-hash 0.03(0.00+0.02) 5313.5: thin pack size with --full-name-hash 3.0K 5313.6: big pack 1.60(2.87+0.32) 5313.7: big pack size 57.9M 5313.8: big pack with --full-name-hash 1.41(1.94+0.37) 5313.9: big pack size with --full-name-hash 57.8M 5313.10: shallow fetch pack 1.69(2.70+0.22) 5313.11: shallow pack size 33.0M 5313.12: shallow pack with --full-name-hash 1.49(1.84+0.34) 5313.13: shallow pack size with --full-name-hash 33.6M 5313.14: repack 75.10(537.66+5.47) 5313.15: repack size 454.2M 5313.16: repack with --full-name-hash 18.10(92.50+5.14) 5313.17: repack size with --full-name-hash 174.8M

(after my change)

Test this tree --------------------------------------------------------------------- 5313.2: thin pack 0.03(0.01+0.02) 5313.3: thin pack size 1.1K 5313.4: thin pack with --full-name-hash 0.03(0.01+0.02) 5313.5: thin pack size with --full-name-hash 1.1K 5313.6: big pack 1.62(2.94+0.28) 5313.7: big pack size 57.9M 5313.8: big pack with --full-name-hash 1.35(2.07+0.37) 5313.9: big pack size with --full-name-hash 57.6M 5313.10: shallow fetch pack 1.63(2.52+0.29) 5313.11: shallow pack size 33.0M 5313.12: shallow pack with --full-name-hash 1.50(2.10+0.23) 5313.13: shallow pack size with --full-name-hash 33.1M 5313.14: repack 74.86(531.39+5.49) 5313.15: repack size 454.7M 5313.16: repack with --full-name-hash 19.71(111.39+5.12) 5313.17: repack size with --full-name-hash 165.6M

The tests were run by:
  GENERATE_COMPILATION_DATABASE=yes make CC=clang && (cd t/perf && env GIT_PERF_LARGE_REPO=~/tmp/fluentui ./run -- p5313*.sh)

The similarity in sizes looked suspicious, so I replaced the contents of the hash function with "return 0;" and indeed the sizes significantly increased, so hopefully there is nothing wrong with my setup.

The git repo was called out in [1] as demonstrating "some of the issues with this approach", but here are the results, run by:

  GENERATE_COMPILATION_DATABASE=yes make CC=clang && (cd t/perf && ./run -- p5313*.sh)

Test this tree -------------------------------------------------------------------- 5313.2: thin pack 0.03(0.00+0.02) 5313.3: thin pack size 2.9K 5313.4: thin pack with --full-name-hash 0.03(0.00+0.02) 5313.5: thin pack size with --full-name-hash 2.9K 5313.6: big pack 1.69(2.80+0.28) 5313.7: big pack size 18.7M 5313.8: big pack with --full-name-hash 1.68(2.82+0.31) 5313.9: big pack size with --full-name-hash 18.8M 5313.10: shallow fetch pack 0.96(1.47+0.16) 5313.11: shallow pack size 12.1M 5313.12: shallow pack with --full-name-hash 1.01(1.51+0.14) 5313.13: shallow pack size with --full-name-hash 12.1M 5313.14: repack 17.05(69.99+4.33) 5313.15: repack size 116.5M 5313.16: repack with --full-name-hash 15.74(67.03+4.18) 5313.17: repack size with --full-name-hash 116.1M

[1] https://lore.kernel.org/git/c14ef6879e451401381ebbdb8f30d33c8f56c25b.1730775908.git.gitgitgadget@gmail.com/
Show 9 quoted lines
> | Repo     | Standard Repack | With --full-name-hash |
> |----------|-----------------|-----------------------|
> | fluentui |         438 MB  |               168 MB  |
> | Repo B   |       6,255 MB  |               829 MB  |
> | Repo C   |      37,737 MB  |             7,125 MB  |
> | Repo D   |     130,049 MB  |             6,190 MB  |
> | Repo E   |     100,957 MB  |            22,979 MB  |
> | Repo F   |       8,308 MB  |               746 MB  |
> | Repo G   |       4,329 MB  |             3,643 MB  |

If the results are similar for some of the above repos (I do not have access to them), maybe it's worth considering using my hash function (or a variation of it).

I'll also take a look at the rest of the patch set.
---
diff --git a/pack-objects.h b/pack-objects.h
index 88360aa3e8..c4f35eafa0 100644
--- a/pack-objects.h
+++ b/pack-objects.h
@@ -209,23 +209,24 @@ static inline uint32_t pack_name_hash(const char *name)
 
 static inline uint32_t pack_full_name_hash(const char *name)
 {
-       const uint32_t bigp = 1234572167U;
-       uint32_t c, hash = bigp;
+       uint32_t hash = 0, base = 0;
+       uint8_t c;
 
        if (!name)
                return 0;
 
-       /*
-        * Do the simplest thing that will resemble pseudo-randomness: add
-        * random multiples of a large prime number with a binary shift.
-        * The goal is not to be cryptographic, but to be generally
-        * uniformly distributed.
-        */
-       while ((c = *name++) != 0) {
-               hash += c * bigp;
-               hash = (hash >> 5) | (hash << 27);
+       while ((c = (uint8_t) *name++) != 0) {
+               if (isspace(c))
+                       continue;
+               if (c == '/') {
+                       base = (base >> 6) ^ hash;
+                       hash = 0;
+               } else {
+                       uint8_t nybble_swapped = (c >> 4) + ((c & 15) << 4);
+                       hash = (hash >> 2) + (nybble_swapped << 24);
+               }
        }
-       return hash;
+       return (base >> 6) ^ hash;
 }
Previous: Jonathan TanNext: Junio C Hamano
Message 35 of 93 in “pack-objects: Create an alternative name hash algorithm (recreated)”
  1. 0/7 pack-objects: Create an alternative name hash algorithm (recreated)Derrick Stolee via GitGitGadget, Nov 5, 2024
  2. 1/7 pack-objects: add --full-name-hash optionDerrick Stolee via GitGitGadget, Nov 5, 2024
  3. Taylor BlauNov 21, 2024
  4. Taylor BlauNov 21, 2024
  5. Junio C HamanoNov 21, 2024
  6. Derrick StoleeNov 22, 2024
  7. Derrick StoleeNov 22, 2024
  8. Patrick SteinhardtNov 26, 2024
  9. 2/7 repack: add --full-name-hash optionDerrick Stolee via GitGitGadget, Nov 5, 2024
  10. Taylor BlauNov 21, 2024
  11. Derrick StoleeNov 22, 2024
  12. 3/7 pack-objects: add GIT_TEST_FULL_NAME_HASHDerrick Stolee via GitGitGadget, Nov 5, 2024
  13. Taylor BlauNov 21, 2024
  14. Derrick StoleeNov 22, 2024
  15. Jonathan TanNov 22, 2024
  16. Junio C HamanoNov 22, 2024
  17. Jonathan TanNov 22, 2024
  18. Junio C HamanoNov 25, 2024
  19. Jonathan TanNov 25, 2024
  20. Junio C HamanoNov 26, 2024
  21. Patrick SteinhardtNov 26, 2024
  22. 4/7 git-repack: update usage to match docsDerrick Stolee via GitGitGadget, Nov 5, 2024
  23. Taylor BlauNov 21, 2024
  24. Derrick StoleeNov 22, 2024
  25. 5/7 p5313: add size comparison testDerrick Stolee via GitGitGadget, Nov 5, 2024
  26. Taylor BlauNov 21, 2024
  27. Derrick StoleeNov 22, 2024
  28. Patrick SteinhardtNov 26, 2024
  29. 6/7 pack-objects: disable --full-name-hash when shallowDerrick Stolee via GitGitGadget, Nov 5, 2024
  30. Taylor BlauNov 21, 2024
  31. Derrick StoleeNov 22, 2024
  32. 7/7 test-tool: add helper for name-hash valuesDerrick Stolee via GitGitGadget, Nov 5, 2024
  33. Taylor BlauNov 21, 2024
  34. Jonathan TanNov 22, 2024
  35. Jonathan TanNov 21, 2024
  36. Junio C HamanoNov 22, 2024
  37. Junio C HamanoNov 22, 2024
  38. Derrick StoleeNov 22, 2024
  39. Junio C HamanoNov 24, 2024
  40. Jonathan TanNov 22, 2024
  41. 0/8 pack-objects: Create an alternative name hash algorithm (recreated)Derrick Stolee via GitGitGadget, Dec 2, 2024
  42. 1/8 pack-objects: create new name-hash function versionJonathan Tan via GitGitGadget, Dec 2, 2024
  43. karthik nayakDec 4, 2024
  44. Junio C HamanoDec 4, 2024
  45. karthik nayakDec 5, 2024
  46. Jonathan TanDec 9, 2024
  47. Junio C HamanoDec 10, 2024
  48. 2/8 pack-objects: add --name-hash-version optionDerrick Stolee via GitGitGadget, Dec 2, 2024
  49. karthik nayakDec 4, 2024
  50. 3/8 repack: add --name-hash-version optionDerrick Stolee via GitGitGadget, Dec 2, 2024
  51. karthik nayakDec 4, 2024
  52. 4/8 pack-objects: add GIT_TEST_NAME_HASH_VERSIONDerrick Stolee via GitGitGadget, Dec 2, 2024
  53. karthik nayakDec 4, 2024
  54. Jonathan TanDec 9, 2024
  55. Derrick StoleeDec 20, 2024
  56. 5/8 p5313: add size comparison testDerrick Stolee via GitGitGadget, Dec 2, 2024
  57. 6/8 test-tool: add helper for name-hash valuesDerrick Stolee via GitGitGadget, Dec 2, 2024
  58. 7/8 pack-objects: prevent name hash version changeDerrick Stolee via GitGitGadget, Dec 2, 2024
  59. 8/8 pack-objects: add third name hash versionDerrick Stolee via GitGitGadget, Dec 2, 2024
  60. Junio C HamanoDec 3, 2024
  61. Derrick StoleeDec 4, 2024
  62. Junio C HamanoDec 4, 2024
  63. 0/8 pack-objects: Create an alternative name hash algorithm (recreated)Derrick Stolee via GitGitGadget, Dec 20, 2024
  64. 1/8 pack-objects: create new name-hash function versionJonathan Tan via GitGitGadget, Dec 20, 2024
  65. Taylor BlauJan 22, 2025
  66. 2/8 pack-objects: add --name-hash-version optionDerrick Stolee via GitGitGadget, Dec 20, 2024
  67. Taylor BlauJan 22, 2025
  68. Derrick StoleeJan 24, 2025
  69. 3/8 repack: add --name-hash-version optionDerrick Stolee via GitGitGadget, Dec 20, 2024
  70. Taylor BlauJan 22, 2025
  71. 4/8 pack-objects: add GIT_TEST_NAME_HASH_VERSIONDerrick Stolee via GitGitGadget, Dec 20, 2024
  72. Taylor BlauJan 22, 2025
  73. 5/8 p5313: add size comparison testDerrick Stolee via GitGitGadget, Dec 20, 2024
  74. 6/8 test-tool: add helper for name-hash valuesDerrick Stolee via GitGitGadget, Dec 20, 2024
  75. 7/8 pack-objects: prevent name hash version changeDerrick Stolee via GitGitGadget, Dec 20, 2024
  76. Taylor BlauJan 22, 2025
  77. 8/8 pack-objects: add third name hash versionDerrick Stolee via GitGitGadget, Dec 20, 2024
  78. Taylor BlauJan 22, 2025
  79. Derrick StoleeJan 24, 2025
  80. Derrick StoleeJan 21, 2025
  81. Taylor BlauJan 22, 2025
  82. Derrick StoleeJan 24, 2025
  83. 0/7 pack-objects: Create an alternative name hash algorithm (recreated)Derrick Stolee via GitGitGadget, Jan 27, 2025
  84. 1/7 pack-objects: create new name-hash function versionJonathan Tan via GitGitGadget, Jan 27, 2025
  85. 3/7 repack: add --name-hash-version optionDerrick Stolee via GitGitGadget, Jan 27, 2025
  86. 2/7 pack-objects: add --name-hash-version optionDerrick Stolee via GitGitGadget, Jan 27, 2025
  87. Junio C HamanoJan 27, 2025
  88. Derrick StoleeJan 29, 2025
  89. 4/7 pack-objects: add GIT_TEST_NAME_HASH_VERSIONDerrick Stolee via GitGitGadget, Jan 27, 2025
  90. 5/7 p5313: add size comparison testDerrick Stolee via GitGitGadget, Jan 27, 2025
  91. 6/7 test-tool: add helper for name-hash valuesDerrick Stolee via GitGitGadget, Jan 27, 2025
  92. 7/7 pack-objects: prevent name hash version changeDerrick Stolee via GitGitGadget, Jan 27, 2025
  93. Taylor BlauJan 31, 2025

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.