Skip to content

Commit b7e2d8b

Browse files
draftcodegitster
authored andcommitted
fetch: use oidset to keep the want OIDs for faster lookup
During git-fetch, the client checks if the advertised tags' OIDs are already in the fetch request's want OID set. This check is done in a linear scan. For a repository that has a lot of refs, repeating this scan takes 15+ minutes. In order to speed this up, create a oid_set for other refs' OIDs. Signed-off-by: Masaya Suzuki <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 5fa0f52 commit b7e2d8b

File tree

1 file changed

+10
-8
lines changed

1 file changed

+10
-8
lines changed

builtin/fetch.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "refs.h"
88
#include "refspec.h"
99
#include "object-store.h"
10+
#include "oidset.h"
1011
#include "commit.h"
1112
#include "builtin.h"
1213
#include "string-list.h"
@@ -239,15 +240,13 @@ static void add_merge_config(struct ref **head,
239240
}
240241
}
241242

242-
static int will_fetch(struct ref **head, const unsigned char *sha1)
243+
static void create_fetch_oidset(struct ref **head, struct oidset *out)
243244
{
244245
struct ref *rm = *head;
245246
while (rm) {
246-
if (hasheq(rm->old_oid.hash, sha1))
247-
return 1;
247+
oidset_insert(out, &rm->old_oid);
248248
rm = rm->next;
249249
}
250-
return 0;
251250
}
252251

253252
struct refname_hash_entry {
@@ -313,13 +312,15 @@ static void find_non_local_tags(const struct ref *refs,
313312
{
314313
struct hashmap existing_refs;
315314
struct hashmap remote_refs;
315+
struct oidset fetch_oids = OIDSET_INIT;
316316
struct string_list remote_refs_list = STRING_LIST_INIT_NODUP;
317317
struct string_list_item *remote_ref_item;
318318
const struct ref *ref;
319319
struct refname_hash_entry *item = NULL;
320320

321321
refname_hash_init(&existing_refs);
322322
refname_hash_init(&remote_refs);
323+
create_fetch_oidset(head, &fetch_oids);
323324

324325
for_each_ref(add_one_refname, &existing_refs);
325326
for (ref = refs; ref; ref = ref->next) {
@@ -336,9 +337,9 @@ static void find_non_local_tags(const struct ref *refs,
336337
if (item &&
337338
!has_object_file_with_flags(&ref->old_oid,
338339
OBJECT_INFO_QUICK) &&
339-
!will_fetch(head, ref->old_oid.hash) &&
340+
!oidset_contains(&fetch_oids, &ref->old_oid) &&
340341
!has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) &&
341-
!will_fetch(head, item->oid.hash))
342+
!oidset_contains(&fetch_oids, &item->oid))
342343
clear_item(item);
343344
item = NULL;
344345
continue;
@@ -352,7 +353,7 @@ static void find_non_local_tags(const struct ref *refs,
352353
*/
353354
if (item &&
354355
!has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) &&
355-
!will_fetch(head, item->oid.hash))
356+
!oidset_contains(&fetch_oids, &item->oid))
356357
clear_item(item);
357358

358359
item = NULL;
@@ -373,7 +374,7 @@ static void find_non_local_tags(const struct ref *refs,
373374
*/
374375
if (item &&
375376
!has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) &&
376-
!will_fetch(head, item->oid.hash))
377+
!oidset_contains(&fetch_oids, &item->oid))
377378
clear_item(item);
378379

379380
/*
@@ -400,6 +401,7 @@ static void find_non_local_tags(const struct ref *refs,
400401
}
401402
hashmap_free(&remote_refs, 1);
402403
string_list_clear(&remote_refs_list, 0);
404+
oidset_clear(&fetch_oids);
403405
}
404406

405407
static struct ref *get_ref_map(struct remote *remote,

0 commit comments

Comments
 (0)