Skip to content

Commit 5b20ace

Browse files
derrickstoleegitster
authored andcommitted
sha1_name: unroll len loop in find_unique_abbrev_r()
Unroll the while loop inside find_unique_abbrev_r to avoid iterating through all loose objects and packfiles multiple times when the short name is longer than the predicted length. Instead, inspect each object that collides with the estimated abbreviation to find the longest common prefix. The focus of this change is to refactor the existing method in a way that clearly does not change the current behavior. In some cases, the new method is slower than the previous method. Later changes will correct all performance loss. Signed-off-by: Derrick Stolee <[email protected]> Reviewed-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1af8b01 commit 5b20ace

File tree

1 file changed

+42
-15
lines changed

1 file changed

+42
-15
lines changed

sha1_name.c

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -474,10 +474,32 @@ static unsigned msb(unsigned long val)
474474
return r;
475475
}
476476

477-
int find_unique_abbrev_r(char *hex, const unsigned char *sha1, int len)
477+
struct min_abbrev_data {
478+
unsigned int init_len;
479+
unsigned int cur_len;
480+
char *hex;
481+
};
482+
483+
static int extend_abbrev_len(const struct object_id *oid, void *cb_data)
478484
{
479-
int status, exists;
485+
struct min_abbrev_data *mad = cb_data;
486+
487+
char *hex = oid_to_hex(oid);
488+
unsigned int i = mad->init_len;
489+
while (mad->hex[i] && mad->hex[i] == hex[i])
490+
i++;
491+
492+
if (i < GIT_MAX_RAWSZ && i >= mad->cur_len)
493+
mad->cur_len = i + 1;
494+
495+
return 0;
496+
}
480497

498+
int find_unique_abbrev_r(char *hex, const unsigned char *sha1, int len)
499+
{
500+
struct disambiguate_state ds;
501+
struct min_abbrev_data mad;
502+
struct object_id oid_ret;
481503
if (len < 0) {
482504
unsigned long count = approximate_object_count();
483505
/*
@@ -503,19 +525,24 @@ int find_unique_abbrev_r(char *hex, const unsigned char *sha1, int len)
503525
sha1_to_hex_r(hex, sha1);
504526
if (len == GIT_SHA1_HEXSZ || !len)
505527
return GIT_SHA1_HEXSZ;
506-
exists = has_sha1_file(sha1);
507-
while (len < GIT_SHA1_HEXSZ) {
508-
struct object_id oid_ret;
509-
status = get_short_oid(hex, len, &oid_ret, GET_OID_QUIETLY);
510-
if (exists
511-
? !status
512-
: status == SHORT_NAME_NOT_FOUND) {
513-
hex[len] = 0;
514-
return len;
515-
}
516-
len++;
517-
}
518-
return len;
528+
529+
if (init_object_disambiguation(hex, len, &ds) < 0)
530+
return -1;
531+
532+
mad.init_len = len;
533+
mad.cur_len = len;
534+
mad.hex = hex;
535+
536+
ds.fn = extend_abbrev_len;
537+
ds.always_call_fn = 1;
538+
ds.cb_data = (void *)&mad;
539+
540+
find_short_object_filename(&ds);
541+
find_short_packed_object(&ds);
542+
(void)finish_object_disambiguation(&ds, &oid_ret);
543+
544+
hex[mad.cur_len] = 0;
545+
return mad.cur_len;
519546
}
520547

521548
const char *find_unique_abbrev(const unsigned char *sha1, int len)

0 commit comments

Comments
 (0)