commit 9b526dc485a847d4ee78adea32f5cf95dc52d98a from: Stefan Sperling via: Thomas Adam date: Fri Aug 15 14:42:43 2025 UTC improve selection of pack files for pinning in the open pack file cache If two given pack files contain the same amount of requested commits, prefer the pack file which contains the larger amount of total objects to increase our chances of full history traversal. Also, require the first element of the list of requested commits to be present in the pack file since the caller will very likely try to process this commit immediately when we return. This fixes cases where offloading of commit coloring to got-read-pack was ineffective, causing us to take the slow path instead. ok op@ commit - b9c2d47a3fc981f104e3a5b765d8fe555c9d775a commit + 9b526dc485a847d4ee78adea32f5cf95dc52d98a blob - 65325cf16f6257d3decf9839194c56965df6ef68 blob + 6b2c3a52da4fcf2710e181fbca6971dd9e18bdf5 --- lib/pack_create.c +++ lib/pack_create.c @@ -1140,8 +1140,8 @@ got_pack_find_pack_for_commit_painting(struct got_pack *best_packidx = NULL; /* - * Find the largest pack which contains at least some of the - * commits we are interested in. + * Find the largest pack which contains the commit at the head + * of the queue and some other commits we are interested in. */ RB_FOREACH(pe, got_pathlist_head, &repo->packidx_paths) { const char *path_packidx = pe->path; @@ -1154,15 +1154,24 @@ got_pack_find_pack_for_commit_painting(struct got_pack break; nobj = be32toh(packidx->hdr.fanout_table[0xff]); - if (nobj <= nobj_max) + if (nobj < nobj_max) continue; - STAILQ_FOREACH(qid, ids, entry) { + qid = STAILQ_FIRST(ids); + idx = got_packidx_get_object_idx(packidx, &qid->id); + if (idx == -1) + continue; + ncommits++; + + qid = STAILQ_NEXT(qid, entry); + while (qid) { idx = got_packidx_get_object_idx(packidx, &qid->id); if (idx != -1) ncommits++; + qid = STAILQ_NEXT(qid, entry); } - if (ncommits > ncommits_max) { + + if (ncommits >= ncommits_max) { best_packidx_path = path_packidx; nobj_max = nobj; ncommits_max = ncommits; @@ -1277,9 +1286,12 @@ find_pack_for_enumeration(struct got_packidx **best_pa *best_packidx = NULL; + if (nids == 0) + return NULL; + /* - * Find the largest pack which contains at least some of the - * commits and tags we are interested in. + * Find the largest pack which contains the commit at the head + * of the queue and some other commits we are interested in. */ RB_FOREACH(pe, got_pathlist_head, &repo->packidx_paths) { const char *path_packidx = pe->path; @@ -1291,15 +1303,20 @@ find_pack_for_enumeration(struct got_packidx **best_pa break; nobj = be32toh(packidx->hdr.fanout_table[0xff]); - if (nobj <= nobj_max) + if (nobj < nobj_max) + continue; + + idx = got_packidx_get_object_idx(packidx, ids[0]); + if (idx == -1) continue; + ncommits++; - for (i = 0; i < nids; i++) { + for (i = 1; i < nids; i++) { idx = got_packidx_get_object_idx(packidx, ids[i]); if (idx != -1) ncommits++; } - if (ncommits > ncommits_max) { + if (ncommits >= ncommits_max) { best_packidx_path = path_packidx; nobj_max = nobj; ncommits_max = ncommits;