@matheusbsbs / matheus-bagliano / commits / 73cf0822b2
Fork 0

remote: Make ref_remove_duplicates faster for large numbers of refs

The ref_remove_duplicates function was very slow at dealing with very large numbers of refs. This is because it was using a linear search through all remaining refs to find any duplicates of the current ref. Rewriting it to use a string list to keep track of which refs have already been seen and removing duplicates when they are found is much more efficient. Signed-off-by: Julian Phillips <julian@quantumfyre.co.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Julian Phillips committed Oct 25, 2009 at 21:28 UTC 73cf0822b2a4ffa7ad559d1f0772e39718fc7776
1 file changed +22 -19
remote.c
+22 -19
@@ -6,6 +6,7 @@
6 #include "revision.h"
7 #include "dir.h"
8 #include "tag.h"
9 +#include "string-list.h"
10
11 static struct refspec s_tag_refspec = {
12 0,
@@ -734,29 +735,31 @@ int for_each_remote(each_remote_fn fn, void *priv)
735
736 void ref_remove_duplicates(struct ref *ref_map)
737 {
737 - struct ref **posn;
738 - struct ref *next;
739 - for (; ref_map; ref_map = ref_map->next) {
738 + struct string_list refs = { NULL, 0, 0, 0 };
739 + struct string_list_item *item = NULL;
740 + struct ref *prev = NULL, *next = NULL;
741 + for (; ref_map; prev = ref_map, ref_map = next) {
742 + next = ref_map->next;
743 if (!ref_map->peer_ref)
744 continue;
742 - posn = &ref_map->next;
743 - while (*posn) {
744 - if ((*posn)->peer_ref &&
745 - !strcmp((*posn)->peer_ref->name,
746 - ref_map->peer_ref->name)) {
747 - if (strcmp((*posn)->name, ref_map->name))
748 - die("%s tracks both %s and %s",
749 - ref_map->peer_ref->name,
750 - (*posn)->name, ref_map->name);
751 - next = (*posn)->next;
752 - free((*posn)->peer_ref);
753 - free(*posn);
754 - *posn = next;
755 - } else {
756 - posn = &(*posn)->next;
757 - }
745 +
746 + item = string_list_lookup(ref_map->peer_ref->name, &refs);
747 + if (item) {
748 + if (strcmp(((struct ref *)item->util)->name,
749 + ref_map->name))
750 + die("%s tracks both %s and %s",
751 + ref_map->peer_ref->name,
752 + ((struct ref *)item->util)->name,
753 + ref_map->name);
754 + prev->next = ref_map->next;
755 + free(ref_map->peer_ref);
756 + free(ref_map);
757 }
758 +
759 + item = string_list_insert(ref_map->peer_ref->name, &refs);
760 + item->util = ref_map;
761 }
762 + string_list_clear(&refs, 0);
763 }
764
765 int remote_has_url(struct remote *remote, const char *url)