Skip to content

Commit f09d546

Browse files
author
Liu Zhongbo
committed
builtin/fetch: iterate symrefs instead of all when checking dangling refs
refs_warn_dangling_symref() traverse all references to check if there are any dangling symbolic references. The complexity is O(number of deleted references * total number of references). It will take a lot of time if there are tens of thousands of branches in monorepo. So I first identified all the symbolic references, and then only traverse in these references. The complexity is O (number of deleted references * number of symbolic references). Due to the infrequent use of symbolic references, there will be significant performance improvements here. In my case, the prune_refs() time has been reduced from 20 seconds to 4 seconds. Signed-off-by: Liu Zhongbo <[email protected]>
1 parent ef8ce8f commit f09d546

File tree

3 files changed

+34
-12
lines changed

3 files changed

+34
-12
lines changed

builtin/fetch.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,15 +1412,18 @@ static int prune_refs(struct display_state *display_state,
14121412

14131413
if (verbosity >= 0) {
14141414
int summary_width = transport_summary_width(stale_refs);
1415+
struct string_list symrefs = STRING_LIST_INIT_NODUP;
1416+
refs_get_symrefs(get_main_ref_store(the_repository), &symrefs);
14151417

14161418
for (ref = stale_refs; ref; ref = ref->next) {
14171419
display_ref_update(display_state, '-', _("[deleted]"), NULL,
14181420
_("(none)"), ref->name,
14191421
&ref->new_oid, &ref->old_oid,
14201422
summary_width);
1421-
refs_warn_dangling_symref(get_main_ref_store(the_repository),
1422-
stderr, dangling_msg, ref->name);
1423+
refs_warn_dangling_symref(get_main_ref_store(the_repository), stderr,
1424+
dangling_msg, ref->name, &symrefs);
14231425
}
1426+
string_list_clear(&symrefs, 0);
14241427
}
14251428

14261429
cleanup:

refs.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -463,16 +463,33 @@ static int warn_if_dangling_symref(const char *refname, const char *referent UNU
463463
return 0;
464464
}
465465

466-
void refs_warn_dangling_symref(struct ref_store *refs, FILE *fp,
467-
const char *msg_fmt, const char *refname)
466+
static int append_symref(const char *refname, const char *referent UNUSED,
467+
const struct object_id *oid UNUSED,
468+
int flags, void *cb_data) {
469+
struct string_list *d = cb_data;
470+
if ((flags & REF_ISSYMREF)){
471+
string_list_append(d, refname);
472+
}
473+
return 0;
474+
}
475+
476+
void refs_get_symrefs(struct ref_store *refs, struct string_list *refnames)
468477
{
469-
struct warn_if_dangling_data data = {
470-
.refs = refs,
471-
.fp = fp,
472-
.refname = refname,
473-
.msg_fmt = msg_fmt,
474-
};
475-
refs_for_each_rawref(refs, warn_if_dangling_symref, &data);
478+
refs_for_each_rawref(refs, append_symref, refnames);
479+
}
480+
481+
void refs_warn_dangling_symref(struct ref_store *refs, FILE *fp,
482+
const char *msg_fmt, const char *refname, struct string_list *symrefs) {
483+
const char *resolves_to;
484+
struct string_list_item *symref;
485+
for_each_string_list_item(symref, symrefs) {
486+
resolves_to = refs_resolve_ref_unsafe(refs, symref->string,
487+
0, NULL, NULL);
488+
if (resolves_to && strcmp(resolves_to, refname) == 0) {
489+
fprintf(fp, msg_fmt, symref->string);
490+
fputc('\n', fp);
491+
}
492+
}
476493
}
477494

478495
void refs_warn_dangling_symrefs(struct ref_store *refs, FILE *fp,

refs.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,8 +394,10 @@ static inline const char *has_glob_specials(const char *pattern)
394394
return strpbrk(pattern, "?*[");
395395
}
396396

397+
void refs_get_symrefs(struct ref_store *refs, struct string_list *refnames);
398+
397399
void refs_warn_dangling_symref(struct ref_store *refs, FILE *fp,
398-
const char *msg_fmt, const char *refname);
400+
const char *msg_fmt, const char *refname, struct string_list *symrefs);
399401
void refs_warn_dangling_symrefs(struct ref_store *refs, FILE *fp,
400402
const char *msg_fmt, const struct string_list *refnames);
401403

0 commit comments

Comments
 (0)