Skip to content

Commit 0e28161

Browse files
committed
Merge branch 'pr/remotes-in-hashmap'
Optimize remotes configuration look-up in a repository with very many remotes defined. * pr/remotes-in-hashmap: use a hashmap to make remotes faster
2 parents 44ceb79 + d0da003 commit 0e28161

File tree

2 files changed

+49
-17
lines changed

2 files changed

+49
-17
lines changed

remote.c

+46-17
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct rewrites {
4242
static struct remote **remotes;
4343
static int remotes_alloc;
4444
static int remotes_nr;
45+
static struct hashmap remotes_hash;
4546

4647
static struct branch **branches;
4748
static int branches_alloc;
@@ -136,26 +137,51 @@ static void add_url_alias(struct remote *remote, const char *url)
136137
add_pushurl_alias(remote, url);
137138
}
138139

140+
struct remotes_hash_key {
141+
const char *str;
142+
int len;
143+
};
144+
145+
static int remotes_hash_cmp(const struct remote *a, const struct remote *b, const struct remotes_hash_key *key)
146+
{
147+
if (key)
148+
return strncmp(a->name, key->str, key->len) || a->name[key->len];
149+
else
150+
return strcmp(a->name, b->name);
151+
}
152+
153+
static inline void init_remotes_hash(void)
154+
{
155+
if (!remotes_hash.cmpfn)
156+
hashmap_init(&remotes_hash, (hashmap_cmp_fn)remotes_hash_cmp, 0);
157+
}
158+
139159
static struct remote *make_remote(const char *name, int len)
140160
{
141-
struct remote *ret;
142-
int i;
161+
struct remote *ret, *replaced;
162+
struct remotes_hash_key lookup;
163+
struct hashmap_entry lookup_entry;
143164

144-
for (i = 0; i < remotes_nr; i++) {
145-
if (len ? (!strncmp(name, remotes[i]->name, len) &&
146-
!remotes[i]->name[len]) :
147-
!strcmp(name, remotes[i]->name))
148-
return remotes[i];
149-
}
165+
if (!len)
166+
len = strlen(name);
167+
168+
init_remotes_hash();
169+
lookup.str = name;
170+
lookup.len = len;
171+
hashmap_entry_init(&lookup_entry, memhash(name, len));
172+
173+
if ((ret = hashmap_get(&remotes_hash, &lookup_entry, &lookup)) != NULL)
174+
return ret;
150175

151176
ret = xcalloc(1, sizeof(struct remote));
152177
ret->prune = -1; /* unspecified */
153178
ALLOC_GROW(remotes, remotes_nr + 1, remotes_alloc);
154179
remotes[remotes_nr++] = ret;
155-
if (len)
156-
ret->name = xstrndup(name, len);
157-
else
158-
ret->name = xstrdup(name);
180+
ret->name = xstrndup(name, len);
181+
182+
hashmap_entry_init(ret, lookup_entry.hash);
183+
replaced = hashmap_put(&remotes_hash, ret);
184+
assert(replaced == NULL); /* no previous entry overwritten */
159185
return ret;
160186
}
161187

@@ -717,13 +743,16 @@ struct remote *pushremote_get(const char *name)
717743

718744
int remote_is_configured(const char *name)
719745
{
720-
int i;
746+
struct remotes_hash_key lookup;
747+
struct hashmap_entry lookup_entry;
721748
read_config();
722749

723-
for (i = 0; i < remotes_nr; i++)
724-
if (!strcmp(name, remotes[i]->name))
725-
return 1;
726-
return 0;
750+
init_remotes_hash();
751+
lookup.str = name;
752+
lookup.len = strlen(name);
753+
hashmap_entry_init(&lookup_entry, memhash(name, lookup.len));
754+
755+
return hashmap_get(&remotes_hash, &lookup_entry, &lookup) != NULL;
727756
}
728757

729758
int for_each_remote(each_remote_fn fn, void *priv)

remote.h

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define REMOTE_H
33

44
#include "parse-options.h"
5+
#include "hashmap.h"
56

67
enum {
78
REMOTE_CONFIG,
@@ -10,6 +11,8 @@ enum {
1011
};
1112

1213
struct remote {
14+
struct hashmap_entry ent; /* must be first */
15+
1316
const char *name;
1417
int origin;
1518

0 commit comments

Comments
 (0)