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

[PATCH] midx.c: use `pack-objects --stdin-packs` when repacking

From
Taylor Blau <me@ttaylorr.com>
Date
Sep 20, 2022, 02:08 UTC
Message-ID
<9195a9ecd11a19f2c7fb1c70136d2d13fa308010.1663639662.git.me@ttaylorr.com>

The `git multi-pack-index repack` command aggregates all objects in certain packs contained in the MIDX, largely dictated by the value of its `--batch-size` parameter.

To create the new pack, the MIDX machinery spawns a `pack-objects` sub-process, which it feeds the object IDs in each of the pack(s) that it wants to aggregate.

This implementation, which dates back to ce1e4a105b (midx: implement midx_repack(), 2019-06-10), predates the `--stdin-packs` mode in `pack-objects`. This mode (which was introduced a couple of years later in 339bce27f4 (builtin/pack-objects.c: add '--stdin-packs' option, 2021-02-22)) allows `pack-objects` callers to specify the contents of the output pack by indicating which packs to aggregate.

This patch replaces the pre-`--stdin-packs` invocation (where each object is given to `pack-objects` one by one) with the more modern `--stdin-packs` option.

This allows us to avoid some CPU cycles serializing and deserializing every object ID in all of the packs we're aggregating. It also avoids us having to send a potentially large amount of data down to `pack-objects`.

But more importantly, it generates slightly higher quality (read: more tightly compressed) packs, because of the reachability traversal that `--stdin-packs` does after the fact in order to gather namehash values which seed the delta selection process.

In practice, this seems to add a slight amount of overhead (on the order of a few seconds for git.git broken up into ~100 packs), in exchange for a modest reduction (on the order of ~3.5%) in the resulting pack size.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
---
Noticed this while working on a semi-related series in:
  https://lore.kernel.org/git/cover.1663638929.git.me@ttaylorr.com/T/

the savings here are pretty modest, but this is in line with the strategy we use in the `--geometric` repack mode, which performs a similar task.

 midx.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/midx.c b/midx.c
index c27d0e5f15..c06f0f00e6 100644
--- a/midx.c
+++ b/midx.c
@@ -1973,6 +1973,7 @@ int midx_repack(struct repository *r, const char *object_dir, size_t batch_size,
 	struct child_process cmd = CHILD_PROCESS_INIT;
 	FILE *cmd_in;
 	struct strbuf base_name = STRBUF_INIT;
+	struct strbuf scratch = STRBUF_INIT;
 	struct multi_pack_index *m = lookup_multi_pack_index(r, object_dir);

 	/*
@@ -1997,7 +1998,7 @@ int midx_repack(struct repository *r, const char *object_dir, size_t batch_size,
 	repo_config_get_bool(r, "repack.usedeltabaseoffset", &delta_base_offset);
 	repo_config_get_bool(r, "repack.usedeltaislands", &use_delta_islands);

-	strvec_push(&cmd.args, "pack-objects");
+	strvec_pushl(&cmd.args, "pack-objects", "--stdin-packs", NULL);

 	strbuf_addstr(&base_name, object_dir);
 	strbuf_addstr(&base_name, "/pack/pack");
@@ -2026,17 +2027,17 @@ int midx_repack(struct repository *r, const char *object_dir, size_t batch_size,

 	cmd_in = xfdopen(cmd.in, "w");

-	for (i = 0; i < m->num_objects; i++) {
-		struct object_id oid;
-		uint32_t pack_int_id = nth_midxed_pack_int_id(m, i);
+	for (i = 0; i < m->num_packs; i++) {
+		strbuf_reset(&scratch);

-		if (!include_pack[pack_int_id])
-			continue;
+		strbuf_addstr(&scratch, m->pack_names[i]);
+		strbuf_strip_suffix(&scratch, ".idx");
+		strbuf_addstr(&scratch, ".pack");

-		nth_midxed_object_oid(&oid, m, i);
-		fprintf(cmd_in, "%s\n", oid_to_hex(&oid));
+		fprintf(cmd_in, "%s%s\n", include_pack[i] ? "" : "^", scratch.buf);
 	}
 	fclose(cmd_in);
+	strbuf_release(&scratch);

 	if (finish_command(&cmd)) {
 		error(_("could not finish pack-objects"));
--
2.37.0.1.g1379af2e9d
Next: Taylor Blau
Message 1 of 6 in “midx.c: use `pack-objects --stdin-packs` when repacking”
  1. midx.c: use `pack-objects --stdin-packs` when repackingTaylor Blau, Sep 20, 2022
  2. Taylor BlauSep 20, 2022
  3. Jeff KingSep 20, 2022
  4. Taylor BlauSep 20, 2022
  5. Jeff KingSep 20, 2022
  6. Taylor BlauSep 20, 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.