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

Re: [PATCH 2/6] pack-bitmap: prepare to read lookup table extension

From
Derrick Stolee <derrickstolee@github.com>
Date
Jun 20, 2022, 20:49 UTC
Message-ID
<92dc6860-ff35-0989-5114-fe1e220ca10c@github.com>
In-Reply-To
<d139a4c48aa058b142c4860721b10344c5498031.1655728395.git.gitgitgadget@gmail.com>
On 6/20/2022 8:33 AM, Abhradeep Chakraborty via GitGitGadget wrote:
> From: Abhradeep Chakraborty <chakrabortyabhradeep79@gmail.com>
> 
> Bitmap lookup table extension can let git to parse only the necessary
> bitmaps without loading the previous bitmaps one by one.
Here is an attempt to reword this a bit:
  The bitmap lookup table extension was documented by an earlier
  change, but Git does not yet know how to parse that information.
  The extension allows parsing a smaller portion of the bitmap
  file in order to find bitmaps for specific commits.
 
> Teach git to read and use the bitmap lookup table extension.

Normally, I don't mind doing the read portion after the write portion, but it would be nice to have them in the opposite order so we can test writing the extension _and Git ignoring the extension_ before implementing the parsing. As it stands, most of the code in this patch is untested until patch 5.

General outline attempt:
1. Document the format.
2. Write the extension if the flag is given.
3. Add pack.writeBitmapLookupTable and add tests that write
   the lookup table (and do other bitmap reads on that data).
4. Read the lookup table. The tests from step 3 already cover
   acting upon the lookup table. (Perhaps we add a mode here
   that disables GIT_READ_COMMIT_TABLE since that is not used
   anywhere else.)
5. Performance tests.
> +		if (flags & BITMAP_OPT_LOOKUP_TABLE &&
> +		    git_env_bool("GIT_READ_COMMIT_TABLE", 1)) {

This environment variable does not appear to be used or documented anywhere. Do we really want to use it as a way to disable reading the lookup table in general? Or would it be better to have a GIT_TEST_* variable for disabling the read during testing?

Show 6 quoted lines
> +			uint32_t entry_count = ntohl(header->entry_count);
> +			uint32_t table_size =
> +				(entry_count * the_hash_algo->rawsz) /* oids */ +
> +				(entry_count * sizeof(uint32_t)) /* offsets */ +
> +				(entry_count * sizeof(uint32_t)) /* xor offsets */ +
> +				(sizeof(uint32_t)) /* flags */;

Here, uint32_T is probably fine, but maybe we should just use size_t instead? Should we use st_mult() and st_add() everywhere?

Note: you're using the_hash_algo->rawsz here, which makes sense
because the bitmap format doesn't specify which hash algorithm is
used. Just making this note to say that we should include the hash
algorithm as a value in the bitmap format when we increment the
format version (in the future).
Show 5 quoted lines
> +			if (table_size > index_end - index->map - header_size)
> +				return error("corrupted bitmap index file (too short to fit commit table)");
> +
> +			index->table_lookup = (void *)(index_end - table_size);
> +			index->table_offsets = index->table_lookup + the_hash_algo->rawsz * entry_count;
st_mult(), st_add()? Or, should we assume safety now?
> +			index_end -= table_size;
> +		}
> -	if (load_bitmap_entries_v1(bitmap_git) < 0)
> +	if (!bitmap_git->table_lookup && load_bitmap_entries_v1(bitmap_git) < 0)
>  		goto failed;
Ok, don't load these entries pre-emptively if we have the lookup table.
> +static struct stored_bitmap *stored_bitmap_for_commit(struct bitmap_index *bitmap_git,
> +						      struct commit *commit,
> +						      uint32_t *pos_hint);

I see that we have a two-method recursion loop. Please move this declaration to immediately before lazy_bitmap_for_commit() so it is declared as late as possible.

Show 5 quoted lines
> +static inline const unsigned char *bitmap_oid_pos(struct bitmap_index *bitmap_git,
> +						  uint32_t pos)
> +{
> +	return bitmap_git->table_lookup + (pos * the_hash_algo->rawsz);
> +}

I would call this "bitmap_hash_pos()" because we are getting a raw hash and not a 'struct object_id'. Do you want a helper that fills a 'struct object_id', perhaps passed-by-reference?

> +static inline const void *bitmap_offset_pos(struct bitmap_index *bitmap_git,
> +					    uint32_t pos)
> +static inline const void *xor_position_pos(struct bitmap_index *bitmap_git,
> +					   uint32_t pos)

These two helpers should probably return a size_t and uint32_t instead of a pointer. Let these do get_be[32|64]() on the computed pointer.

Show 10 quoted lines
> +static int bitmap_table_lookup(struct bitmap_index *bitmap_git,
> +			       struct object_id *oid,
> +			       uint32_t *commit_pos)
> +{
> +	unsigned char *found = bsearch(oid->hash, bitmap_git->table_lookup,
> +				       bitmap_git->entry_count,
> +				       the_hash_algo->rawsz, bitmap_lookup_cmp);
> +	if (found)
> +		*commit_pos = (found - bitmap_git->table_lookup) / the_hash_algo->rawsz;
> +	return !!found;

Ok, we are running binary search and converting the pointer into a position.

Frequently, these kind of searches return an int, but use a negative value to indicate that the value was not found. Using an int in this way would restrict us to 2^31 bitmaps instead of 2^32, so maybe it is not worth matching that practice.

Show 13 quoted lines
> +static struct stored_bitmap *lazy_bitmap_for_commit(struct bitmap_index *bitmap_git,
> +						    struct object_id *oid,
> +						    uint32_t commit_pos)
> +{
> +	uint32_t xor_pos;
> +	off_t bitmap_ofs;
> +
> +	int flags;
> +	struct ewah_bitmap *bitmap;
> +	struct stored_bitmap *xor_bitmap;
> +
> +	bitmap_ofs = get_be32(bitmap_offset_pos(bitmap_git, commit_pos));
> +	xor_pos = get_be32(xor_position_pos(bitmap_git, commit_pos));

These lines become simpler with a change in the helper methods' prototypes, as I recommended higher up.

Show 21 quoted lines
> +	/*
> +	 * Lazily load the xor'd bitmap if required (and we haven't done so
> +	 * already). Make sure to pass the xor'd bitmap's position along as a
> +	 * hint to avoid an unnecessary binary search in
> +	 * stored_bitmap_for_commit().
> +	 */
> +	if (xor_pos == 0xffffffff) {
> +		xor_bitmap = NULL;
> +	} else {
> +		struct commit *xor_commit;
> +		struct object_id xor_oid;
> +
> +		oidread(&xor_oid, bitmap_oid_pos(bitmap_git, xor_pos));
> +
> +		xor_commit = lookup_commit(the_repository, &xor_oid);
> +		if (!xor_commit)
> +			return NULL;
> +
> +		xor_bitmap = stored_bitmap_for_commit(bitmap_git, xor_commit,
> +						      &xor_pos);
> +	}

This is using an interesting type of tail-recursion. We might be better off using a loop with a stack: push to the stack the commit positions of the XOR bitmaps. At the very bottom, we get a bitmap without an XOR base. Then, pop off the stack, modifying the bitmap with XOR operations as we go. (Perhaps we also store these bitmaps in-memory along the way?) Finally, we have the necessary bitmap.

This iterative approach avoids possible stack exhaustion if there are long XOR chains in the file.

Show 31 quoted lines
> +
> +	/*
> +	 * Don't bother reading the commit's index position or its xor
> +	 * offset:
> +	 *
> +	 *   - The commit's index position is irrelevant to us, since
> +	 *     load_bitmap_entries_v1 only uses it to learn the object
> +	 *     id which is used to compute the hashmap's key. We already
> +	 *     have an object id, so no need to look it up again.
> +	 *
> +	 *   - The xor_offset is unusable for us, since it specifies how
> +	 *     many entries previous to ours we should look at. This
> +	 *     makes sense when reading the bitmaps sequentially (as in
> +	 *     load_bitmap_entries_v1()), since we can keep track of
> +	 *     each bitmap as we read them.
> +	 *
> +	 *     But it can't work for us, since the bitmap's don't have a
> +	 *     fixed size. So we learn the position of the xor'd bitmap
> +	 *     from the commit table (and resolve it to a bitmap in the
> +	 *     above if-statement).
> +	 *
> +	 * Instead, we can skip ahead and immediately read the flags and
> +	 * ewah bitmap.
> +	 */
> +	bitmap_git->map_pos = bitmap_ofs + sizeof(uint32_t) + sizeof(uint8_t);
> +	flags = read_u8(bitmap_git->map, &bitmap_git->map_pos);
> +	bitmap = read_bitmap_1(bitmap_git);
> +	if (!bitmap)
> +		return NULL;
> +
> +	return store_bitmap(bitmap_git, bitmap, oid, xor_bitmap, flags);

Looks like we'd want to call store_bitmap() while popping the stack in the loop I recommended above.

Show 23 quoted lines
> +}
> +
> +static struct stored_bitmap *stored_bitmap_for_commit(struct bitmap_index *bitmap_git,
> +						      struct commit *commit,
> +						      uint32_t *pos_hint)
>  {
>  	khiter_t hash_pos = kh_get_oid_map(bitmap_git->bitmaps,
>  					   commit->object.oid);
> -	if (hash_pos >= kh_end(bitmap_git->bitmaps))
> +	if (hash_pos >= kh_end(bitmap_git->bitmaps)) {
> +		uint32_t commit_pos;
> +		if (!bitmap_git->table_lookup)
> +			return NULL;
> +
> +		/* NEEDSWORK: cache misses aren't recorded. */
> +		if (pos_hint)
> +			commit_pos = *pos_hint;
> +		else if (!bitmap_table_lookup(bitmap_git,
> +					      &commit->object.oid,
> +					      &commit_pos))
> +			return NULL;
> +		return lazy_bitmap_for_commit(bitmap_git, &commit->object.oid,
> +					      commit_pos);

The extra bonus of going incremental is that we don't have recursion across two methods, which I always find difficult to reason about.

> +	}
> +	return kh_value(bitmap_git->bitmaps, hash_pos);
> +}
Show 5 quoted lines
> @@ -26,6 +26,7 @@ struct bitmap_disk_header {
>  enum pack_bitmap_opts {
>  	BITMAP_OPT_FULL_DAG = 1,
>  	BITMAP_OPT_HASH_CACHE = 4,
> +	BITMAP_OPT_LOOKUP_TABLE = 16,

Perhaps it is time to use hexadecimal representation here to match the file format document?

Thanks, -Stolee

Previous: Abhradeep Chakraborty via GitGitGadgetNext: Abhradeep Chakraborty
Message 16 of 162 in “[GSoC] bitmap: integrate a lookup table extension to the bitmap format”
  1. 0/6 [GSoC] bitmap: integrate a lookup table extension to the bitmap formatAbhradeep Chakraborty via GitGitGadget, Jun 20, 2022
  2. 1/6 Documentation/technical: describe bitmap lookup table extensionAbhradeep Chakraborty via GitGitGadget, Jun 20, 2022
  3. Derrick StoleeJun 20, 2022
  4. Taylor BlauJun 20, 2022
  5. Abhradeep ChakrabortyJun 21, 2022
  6. Taylor BlauJun 22, 2022
  7. Abhradeep ChakrabortyJun 21, 2022
  8. Taylor BlauJun 20, 2022
  9. Abhradeep ChakrabortyJun 21, 2022
  10. Taylor BlauJun 22, 2022
  11. Abhradeep ChakrabortyJun 22, 2022
  12. Derrick StoleeJun 20, 2022
  13. Abhradeep ChakrabortyJun 21, 2022
  14. Taylor BlauJun 22, 2022
  15. 2/6 pack-bitmap: prepare to read lookup table extensionAbhradeep Chakraborty via GitGitGadget, Jun 20, 2022
  16. Derrick StoleeJun 20, 2022
  17. Abhradeep ChakrabortyJun 21, 2022
  18. Taylor BlauJun 20, 2022
  19. Abhradeep ChakrabortyJun 21, 2022
  20. Taylor BlauJun 22, 2022
  21. Abhradeep ChakrabortyJun 22, 2022
  22. Taylor BlauJun 22, 2022
  23. 3/6 pack-bitmap-write.c: write lookup table extensionAbhradeep Chakraborty via GitGitGadget, Jun 20, 2022
  24. Taylor BlauJun 20, 2022
  25. Abhradeep ChakrabortyJun 21, 2022
  26. Taylor BlauJun 22, 2022
  27. 5/6 bitmap-commit-table: add tests for the bitmap lookup tableAbhradeep Chakraborty via GitGitGadget, Jun 20, 2022
  28. Taylor BlauJun 22, 2022
  29. 4/6 builtin/pack-objects.c: learn pack.writeBitmapLookupTableTaylor Blau via GitGitGadget, Jun 20, 2022
  30. Taylor BlauJun 20, 2022
  31. 6/6 bitmap-lookup-table: add performance testsAbhradeep Chakraborty via GitGitGadget, Jun 20, 2022
  32. Taylor BlauJun 22, 2022
  33. 0/6 [GSoC] bitmap: integrate a lookup table extension to the bitmap formatAbhradeep Chakraborty via GitGitGadget, Jun 26, 2022
  34. 1/6 Documentation/technical: describe bitmap lookup table extensionAbhradeep Chakraborty via GitGitGadget, Jun 26, 2022
  35. Derrick StoleeJun 27, 2022
  36. Taylor BlauJun 27, 2022
  37. Abhradeep ChakrabortyJun 27, 2022
  38. 2/6 pack-bitmap-write.c: write lookup table extensionAbhradeep Chakraborty via GitGitGadget, Jun 26, 2022
  39. Derrick StoleeJun 27, 2022
  40. Taylor BlauJun 27, 2022
  41. Abhradeep ChakrabortyJun 27, 2022
  42. Taylor BlauJun 27, 2022
  43. Abhradeep ChakrabortyJun 27, 2022
  44. 3/6 pack-bitmap-write: learn pack.writeBitmapLookupTable and add testsAbhradeep Chakraborty via GitGitGadget, Jun 26, 2022
  45. Derrick StoleeJun 27, 2022
  46. 3/6 pack-bitmap-write: learn pack.writeBitmapLookupTable and add testsAbhradeep Chakraborty, Jun 27, 2022
  47. Taylor BlauJun 27, 2022
  48. Taylor BlauJun 27, 2022
  49. Abhradeep ChakrabortyJun 27, 2022
  50. Taylor BlauJun 29, 2022
  51. 5/6 bitmap-lookup-table: add performance tests for lookup tableAbhradeep Chakraborty via GitGitGadget, Jun 26, 2022
  52. Taylor BlauJun 27, 2022
  53. Abhradeep ChakrabortyJun 28, 2022
  54. Taylor BlauJun 29, 2022
  55. 6/6 p5310-pack-bitmaps.sh: enable pack.writeReverseIndex for testingAbhradeep Chakraborty via GitGitGadget, Jun 26, 2022
  56. Taylor BlauJun 27, 2022
  57. Abhradeep ChakrabortyJun 28, 2022
  58. 4/6 pack-bitmap: prepare to read lookup table extensionAbhradeep Chakraborty via GitGitGadget, Jun 26, 2022
  59. Derrick StoleeJun 27, 2022
  60. Abhradeep ChakrabortyJun 27, 2022
  61. Derrick StoleeJun 27, 2022
  62. Taylor BlauJun 27, 2022
  63. Abhradeep ChakrabortyJun 28, 2022
  64. Taylor BlauJun 29, 2022
  65. Abhradeep ChakrabortyJun 30, 2022
  66. Taylor BlauJun 27, 2022
  67. Abhradeep ChakrabortyJun 28, 2022
  68. Taylor BlauJun 29, 2022
  69. Taylor BlauJun 29, 2022
  70. Abhradeep ChakrabortyJun 30, 2022
  71. 0/6 [GSoC] bitmap: integrate a lookup table extension to the bitmap formatAbhradeep Chakraborty via GitGitGadget, Jul 4, 2022
  72. 2/6 pack-bitmap-write.c: write lookup table extensionAbhradeep Chakraborty via GitGitGadget, Jul 4, 2022
  73. Taylor BlauJul 14, 2022
  74. Taylor BlauJul 15, 2022
  75. Abhradeep ChakrabortyJul 15, 2022
  76. Taylor BlauJul 15, 2022
  77. Abhradeep ChakrabortyJul 16, 2022
  78. Taylor BlauJul 26, 2022
  79. Martin ÅgrenJul 18, 2022
  80. 1/6 Documentation/technical: describe bitmap lookup table extensionAbhradeep Chakraborty via GitGitGadget, Jul 4, 2022
  81. Philip OakleyJul 8, 2022
  82. Abhradeep ChakrabortyJul 9, 2022
  83. Philip OakleyJul 10, 2022
  84. Taylor BlauJul 14, 2022
  85. Philip OakleyJul 15, 2022
  86. Abhradeep ChakrabortyJul 15, 2022
  87. 3/6 pack-bitmap-write: learn pack.writeBitmapLookupTable and add testsAbhradeep Chakraborty via GitGitGadget, Jul 4, 2022
  88. 4/6 pack-bitmap: prepare to read lookup table extensionAbhradeep Chakraborty via GitGitGadget, Jul 4, 2022
  89. Taylor BlauJul 15, 2022
  90. Abhradeep ChakrabortyJul 15, 2022
  91. Taylor BlauJul 15, 2022
  92. Martin ÅgrenJul 18, 2022
  93. Abhradeep ChakrabortyJul 18, 2022
  94. Martin ÅgrenJul 18, 2022
  95. Taylor BlauJul 26, 2022
  96. 5/6 bitmap-lookup-table: add performance tests for lookup tableAbhradeep Chakraborty via GitGitGadget, Jul 4, 2022
  97. Taylor BlauJul 15, 2022
  98. Abhradeep ChakrabortyJul 15, 2022
  99. 6/6 p5310-pack-bitmaps.sh: remove pack.writeReverseIndexAbhradeep Chakraborty via GitGitGadget, Jul 4, 2022
  100. Abhradeep ChakrabortyJul 4, 2022
  101. Junio C HamanoJul 6, 2022
  102. Abhradeep ChakrabortyJul 7, 2022
  103. Kaartic SivaraamJul 7, 2022
  104. Abhradeep ChakrabortyJul 7, 2022
  105. 0/6 [GSoC] bitmap: integrate a lookup table extension to the bitmap formatAbhradeep Chakraborty via GitGitGadget, Jul 20, 2022
  106. 1/6 Documentation/technical: describe bitmap lookup table extensionAbhradeep Chakraborty via GitGitGadget, Jul 20, 2022
  107. 2/6 pack-bitmap-write.c: write lookup table extensionAbhradeep Chakraborty via GitGitGadget, Jul 20, 2022
  108. 4/6 pack-bitmap: prepare to read lookup table extensionAbhradeep Chakraborty via GitGitGadget, Jul 20, 2022
  109. 5/6 p5310-pack-bitmaps.sh: enable `pack.writeReverseIndex`Abhradeep Chakraborty via GitGitGadget, Jul 20, 2022
  110. 3/6 pack-bitmap-write: learn pack.writeBitmapLookupTable and add testsAbhradeep Chakraborty via GitGitGadget, Jul 20, 2022
  111. 6/6 bitmap-lookup-table: add performance tests for lookup tableAbhradeep Chakraborty via GitGitGadget, Jul 20, 2022
  112. 0/6 [GSoC] bitmap: integrate a lookup table extension to the bitmap formatAbhradeep Chakraborty via GitGitGadget, Jul 20, 2022
  113. 1/6 Documentation/technical: describe bitmap lookup table extensionAbhradeep Chakraborty via GitGitGadget, Jul 20, 2022
  114. 2/6 pack-bitmap-write.c: write lookup table extensionAbhradeep Chakraborty via GitGitGadget, Jul 20, 2022
  115. Taylor BlauJul 26, 2022
  116. Abhradeep ChakrabortyJul 26, 2022
  117. 4/6 pack-bitmap: prepare to read lookup table extensionAbhradeep Chakraborty via GitGitGadget, Jul 20, 2022
  118. Taylor BlauJul 26, 2022
  119. Abhradeep ChakrabortyJul 26, 2022
  120. Eric SunshineJul 26, 2022
  121. 5/6 p5310-pack-bitmaps.sh: enable `pack.writeReverseIndex`Abhradeep Chakraborty via GitGitGadget, Jul 20, 2022
  122. Taylor BlauJul 26, 2022
  123. Ævar Arnfjörð BjarmasonJul 26, 2022
  124. Derrick StoleeJul 26, 2022
  125. Ævar Arnfjörð BjarmasonJul 26, 2022
  126. Abhradeep ChakrabortyJul 26, 2022
  127. 6/6 bitmap-lookup-table: add performance tests for lookup tableAbhradeep Chakraborty via GitGitGadget, Jul 20, 2022
  128. 3/6 pack-bitmap-write: learn pack.writeBitmapLookupTable and add testsAbhradeep Chakraborty via GitGitGadget, Jul 20, 2022
  129. Johannes SchindelinJul 28, 2022
  130. Abhradeep ChakrabortyAug 2, 2022
  131. Johannes SchindelinAug 2, 2022
  132. Abhradeep ChakrabortyAug 2, 2022
  133. Johannes SchindelinAug 8, 2022
  134. Abhradeep ChakrabortyAug 8, 2022
  135. Johannes SchindelinAug 9, 2022
  136. Abhradeep ChakrabortyAug 9, 2022
  137. Abhradeep ChakrabortyAug 9, 2022
  138. Johannes SchindelinAug 10, 2022
  139. Johannes SchindelinAug 10, 2022
  140. Abhradeep ChakrabortyAug 10, 2022
  141. Derrick StoleeAug 10, 2022
  142. Abhradeep ChakrabortyAug 12, 2022
  143. Derrick StoleeAug 12, 2022
  144. Abhradeep ChakrabortyAug 13, 2022
  145. Taylor BlauAug 16, 2022
  146. Abhradeep ChakrabortyAug 17, 2022
  147. Taylor BlauAug 17, 2022
  148. Taylor BlauAug 19, 2022
  149. Abhradeep ChakrabortyAug 13, 2022
  150. Taylor BlauAug 16, 2022
  151. 0/6 [GSoC] bitmap: integrate a lookup table extension to the bitmap formatAbhradeep Chakraborty via GitGitGadget, Aug 14, 2022
  152. 2/6 bitmap: move `get commit positions` code to `bitmap_writer_finish`Abhradeep Chakraborty via GitGitGadget, Aug 14, 2022
  153. 1/6 Documentation/technical: describe bitmap lookup table extensionAbhradeep Chakraborty via GitGitGadget, Aug 14, 2022
  154. 3/6 pack-bitmap-write.c: write lookup table extensionAbhradeep Chakraborty via GitGitGadget, Aug 14, 2022
  155. 5/6 pack-bitmap: prepare to read lookup table extensionAbhradeep Chakraborty via GitGitGadget, Aug 14, 2022
  156. 4/6 pack-bitmap-write: learn pack.writeBitmapLookupTable and add testsAbhradeep Chakraborty via GitGitGadget, Aug 14, 2022
  157. 6/6 bitmap-lookup-table: add performance tests for lookup tableAbhradeep Chakraborty via GitGitGadget, Aug 14, 2022
  158. Junio C HamanoAug 19, 2022
  159. Johannes SchindelinAug 22, 2022
  160. Taylor BlauAug 22, 2022
  161. Taylor BlauAug 25, 2022
  162. Junio C HamanoAug 26, 2022

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.