Skip to content

Commit 3619802

Browse files
jonathantanmygitster
authored andcommitted
index-pack --promisor: don't check blobs
As a follow-up to the parent of this commit, it was found that not checking for the existence of blobs linked from trees sped up the fetch from 24m47.815s to 2m2.127s. Teach Git to do that. The tradeoff of not checking blobs is documented in a code comment. (Blobs may also be linked from tag objects, but it is impossible to know the type of an object linked from a tag object without looking it up in the object database, so the code for that is untouched.) Signed-off-by: Jonathan Tan <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 911d142 commit 3619802

File tree

1 file changed

+30
-1
lines changed

1 file changed

+30
-1
lines changed

builtin/index-pack.c

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,35 @@ static void record_outgoing_link(const struct object_id *oid)
817817
oidset_insert(&outgoing_links, oid);
818818
}
819819

820+
static void maybe_record_name_entry(const struct name_entry *entry)
821+
{
822+
/*
823+
* Checking only trees here results in a significantly faster packfile
824+
* indexing, but the drawback is that if the packfile to be indexed
825+
* references a local blob only directly (that is, never through a
826+
* local tree), that local blob is in danger of being garbage
827+
* collected. Such a situation may arise if we push local commits,
828+
* including one with a change to a blob in the root tree, and then the
829+
* server incorporates them into its main branch through a "rebase" or
830+
* "squash" merge strategy, and then we fetch the new main branch from
831+
* the server.
832+
*
833+
* This situation has not been observed yet - we have only noticed
834+
* missing commits, not missing trees or blobs. (In fact, if it were
835+
* believed that only missing commits are problematic, one could argue
836+
* that we should also exclude trees during the outgoing link check;
837+
* but it is safer to include them.)
838+
*
839+
* Due to the rarity of the situation (it has not been observed to
840+
* happen in real life), and because the "penalty" in such a situation
841+
* is merely to refetch the missing blob when it's needed (and this
842+
* happens only once - when refetched, the blob goes into a promisor
843+
* pack, so it won't be GC-ed, the tradeoff seems worth it.
844+
*/
845+
if (S_ISDIR(entry->mode))
846+
record_outgoing_link(&entry->oid);
847+
}
848+
820849
static void do_record_outgoing_links(struct object *obj)
821850
{
822851
if (obj->type == OBJ_TREE) {
@@ -831,7 +860,7 @@ static void do_record_outgoing_links(struct object *obj)
831860
*/
832861
return;
833862
while (tree_entry_gently(&desc, &entry))
834-
record_outgoing_link(&entry.oid);
863+
maybe_record_name_entry(&entry);
835864
} else if (obj->type == OBJ_COMMIT) {
836865
struct commit *commit = (struct commit *) obj;
837866
struct commit_list *parents = commit->parents;

0 commit comments

Comments
 (0)