Skip to content

Commit d9d65e9

Browse files
committed
Merge branch 'jk/revision-rewritten-parents-in-prio-queue'
Performance fix for "rev-list --parents -- pathspec". * jk/revision-rewritten-parents-in-prio-queue: revision: use a prio_queue to hold rewritten parents
2 parents 4d8c4da + 8320b1d commit d9d65e9

File tree

2 files changed

+54
-22
lines changed

2 files changed

+54
-22
lines changed

revision.c

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -911,26 +911,11 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
911911
commit->object.flags |= TREESAME;
912912
}
913913

914-
static void commit_list_insert_by_date_cached(struct commit *p, struct commit_list **head,
915-
struct commit_list *cached_base, struct commit_list **cache)
916-
{
917-
struct commit_list *new_entry;
918-
919-
if (cached_base && p->date < cached_base->item->date)
920-
new_entry = commit_list_insert_by_date(p, &cached_base->next);
921-
else
922-
new_entry = commit_list_insert_by_date(p, head);
923-
924-
if (cache && (!*cache || p->date < (*cache)->item->date))
925-
*cache = new_entry;
926-
}
927-
928914
static int process_parents(struct rev_info *revs, struct commit *commit,
929-
struct commit_list **list, struct commit_list **cache_ptr)
915+
struct commit_list **list, struct prio_queue *queue)
930916
{
931917
struct commit_list *parent = commit->parents;
932918
unsigned left_flag;
933-
struct commit_list *cached_base = cache_ptr ? *cache_ptr : NULL;
934919

935920
if (commit->object.flags & ADDED)
936921
return 0;
@@ -966,7 +951,9 @@ static int process_parents(struct rev_info *revs, struct commit *commit,
966951
continue;
967952
p->object.flags |= SEEN;
968953
if (list)
969-
commit_list_insert_by_date_cached(p, list, cached_base, cache_ptr);
954+
commit_list_insert_by_date(p, list);
955+
if (queue)
956+
prio_queue_put(queue, p);
970957
}
971958
return 0;
972959
}
@@ -1006,7 +993,9 @@ static int process_parents(struct rev_info *revs, struct commit *commit,
1006993
if (!(p->object.flags & SEEN)) {
1007994
p->object.flags |= SEEN;
1008995
if (list)
1009-
commit_list_insert_by_date_cached(p, list, cached_base, cache_ptr);
996+
commit_list_insert_by_date(p, list);
997+
if (queue)
998+
prio_queue_put(queue, p);
1010999
}
10111000
if (revs->first_parent_only)
10121001
break;
@@ -3345,14 +3334,14 @@ int prepare_revision_walk(struct rev_info *revs)
33453334
return 0;
33463335
}
33473336

3348-
static enum rewrite_result rewrite_one(struct rev_info *revs, struct commit **pp)
3337+
static enum rewrite_result rewrite_one_1(struct rev_info *revs,
3338+
struct commit **pp,
3339+
struct prio_queue *queue)
33493340
{
3350-
struct commit_list *cache = NULL;
3351-
33523341
for (;;) {
33533342
struct commit *p = *pp;
33543343
if (!revs->limited)
3355-
if (process_parents(revs, p, &revs->commits, &cache) < 0)
3344+
if (process_parents(revs, p, NULL, queue) < 0)
33563345
return rewrite_one_error;
33573346
if (p->object.flags & UNINTERESTING)
33583347
return rewrite_one_ok;
@@ -3366,6 +3355,31 @@ static enum rewrite_result rewrite_one(struct rev_info *revs, struct commit **pp
33663355
}
33673356
}
33683357

3358+
static void merge_queue_into_list(struct prio_queue *q, struct commit_list **list)
3359+
{
3360+
while (q->nr) {
3361+
struct commit *item = prio_queue_peek(q);
3362+
struct commit_list *p = *list;
3363+
3364+
if (p && p->item->date >= item->date)
3365+
list = &p->next;
3366+
else {
3367+
p = commit_list_insert(item, list);
3368+
list = &p->next; /* skip newly added item */
3369+
prio_queue_get(q); /* pop item */
3370+
}
3371+
}
3372+
}
3373+
3374+
static enum rewrite_result rewrite_one(struct rev_info *revs, struct commit **pp)
3375+
{
3376+
struct prio_queue queue = { compare_commits_by_commit_date };
3377+
enum rewrite_result ret = rewrite_one_1(revs, pp, &queue);
3378+
merge_queue_into_list(&queue, &revs->commits);
3379+
clear_prio_queue(&queue);
3380+
return ret;
3381+
}
3382+
33693383
int rewrite_parents(struct rev_info *revs, struct commit *commit,
33703384
rewrite_parent_fn_t rewrite_parent)
33713385
{

t/perf/p0001-rev-list.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,24 @@ test_perf 'rev-list --all --objects' '
1414
git rev-list --all --objects >/dev/null
1515
'
1616

17+
test_perf 'rev-list --parents' '
18+
git rev-list --parents HEAD >/dev/null
19+
'
20+
21+
test_expect_success 'create dummy file' '
22+
echo unlikely-to-already-be-there >dummy &&
23+
git add dummy &&
24+
git commit -m dummy
25+
'
26+
27+
test_perf 'rev-list -- dummy' '
28+
git rev-list HEAD -- dummy
29+
'
30+
31+
test_perf 'rev-list --parents -- dummy' '
32+
git rev-list --parents HEAD -- dummy
33+
'
34+
1735
test_expect_success 'create new unreferenced commit' '
1836
commit=$(git commit-tree HEAD^{tree} -p HEAD) &&
1937
test_export commit

0 commit comments

Comments
 (0)