commit 4a35cea75fd93db39197367750ad136b3ee5ee7a from: Stefan Sperling date: Wed Aug 13 12:46:50 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. commit - 60c45cca65d373ac48ea19fead9e1fd4e469d023 commit + 4a35cea75fd93db39197367750ad136b3ee5ee7a blob - 4b84755e2c4557df4a09e1117470fc18cf23bcd9 blob + b0aa5bc15b2f5adb37972b7c68f53df5bbe8485d --- lib/pack_create.c +++ lib/pack_create.c @@ -1143,8 +1143,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; @@ -1157,15 +1157,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; @@ -1280,9 +1289,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; @@ -1294,15 +1306,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;