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 <masayasuzuki@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Masaya Suzuki 2019-09-15 14:18:02 -07:00 committed by Junio C Hamano
parent 5fa0f5238b
commit b7e2d8bca5

View file

@ -7,6 +7,7 @@
#include "refs.h"
#include "refspec.h"
#include "object-store.h"
#include "oidset.h"
#include "commit.h"
#include "builtin.h"
#include "string-list.h"
@ -239,15 +240,13 @@ static void add_merge_config(struct ref **head,
}
}
static int will_fetch(struct ref **head, const unsigned char *sha1)
static void create_fetch_oidset(struct ref **head, struct oidset *out)
{
struct ref *rm = *head;
while (rm) {
if (hasheq(rm->old_oid.hash, sha1))
return 1;
oidset_insert(out, &rm->old_oid);
rm = rm->next;
}
return 0;
}
struct refname_hash_entry {
@ -313,6 +312,7 @@ static void find_non_local_tags(const struct ref *refs,
{
struct hashmap existing_refs;
struct hashmap remote_refs;
struct oidset fetch_oids = OIDSET_INIT;
struct string_list remote_refs_list = STRING_LIST_INIT_NODUP;
struct string_list_item *remote_ref_item;
const struct ref *ref;
@ -320,6 +320,7 @@ static void find_non_local_tags(const struct ref *refs,
refname_hash_init(&existing_refs);
refname_hash_init(&remote_refs);
create_fetch_oidset(head, &fetch_oids);
for_each_ref(add_one_refname, &existing_refs);
for (ref = refs; ref; ref = ref->next) {
@ -336,9 +337,9 @@ static void find_non_local_tags(const struct ref *refs,
if (item &&
!has_object_file_with_flags(&ref->old_oid,
OBJECT_INFO_QUICK) &&
!will_fetch(head, ref->old_oid.hash) &&
!oidset_contains(&fetch_oids, &ref->old_oid) &&
!has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) &&
!will_fetch(head, item->oid.hash))
!oidset_contains(&fetch_oids, &item->oid))
clear_item(item);
item = NULL;
continue;
@ -352,7 +353,7 @@ static void find_non_local_tags(const struct ref *refs,
*/
if (item &&
!has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) &&
!will_fetch(head, item->oid.hash))
!oidset_contains(&fetch_oids, &item->oid))
clear_item(item);
item = NULL;
@ -373,7 +374,7 @@ static void find_non_local_tags(const struct ref *refs,
*/
if (item &&
!has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) &&
!will_fetch(head, item->oid.hash))
!oidset_contains(&fetch_oids, &item->oid))
clear_item(item);
/*
@ -400,6 +401,7 @@ static void find_non_local_tags(const struct ref *refs,
}
hashmap_free(&remote_refs, 1);
string_list_clear(&remote_refs_list, 0);
oidset_clear(&fetch_oids);
}
static struct ref *get_ref_map(struct remote *remote,