Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Commit fbc08ea

Browse files
René Scharfegitster
authored andcommitted
revision: insert unsorted, then sort in prepare_revision_walk()
Speed up prepare_revision_walk() by adding commits without sorting to the commit_list and at the end sort the list in one go. Thanks to mergesort() working behind the scenes, this is a lot faster for large numbers of commits than the current insert sort. Also introduce and use commit_list_reverse(), to keep the ordering of commits sharing the same commit date unchanged. That's because commit_list_insert_by_date() sorts commits with descending date, but adds later entries with the same date entries last, while commit_list_insert() always inserts entries at the top. The following commit_list_sort_by_date() keeps the order of entries sharing the same date. Jeff's test case, in a repo with lots of refs, was to run: # make a new commit on top of HEAD, but not yet referenced sha1=`git commit-tree HEAD^{tree} -p HEAD </dev/null` # now do the same "connected" test that receive-pack would do git rev-list --objects $sha1 --not --all With a git.git with a ref for each revision, master needs (best of five): real 0m2.210s user 0m2.188s sys 0m0.016s And with this patch: real 0m0.480s user 0m0.456s sys 0m0.020s Signed-off-by: Rene Scharfe <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 4690589 commit fbc08ea

File tree

3 files changed

+19
-1
lines changed

3 files changed

+19
-1
lines changed

commit.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,21 @@ struct commit_list *commit_list_insert(struct commit *item, struct commit_list *
361361
return new_list;
362362
}
363363

364+
void commit_list_reverse(struct commit_list **list_p)
365+
{
366+
struct commit_list *prev = NULL, *curr = *list_p, *next;
367+
368+
if (!list_p)
369+
return;
370+
while (curr) {
371+
next = curr->next;
372+
curr->next = prev;
373+
prev = curr;
374+
curr = next;
375+
}
376+
*list_p = prev;
377+
}
378+
364379
unsigned commit_list_count(const struct commit_list *l)
365380
{
366381
unsigned c = 0;

commit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ unsigned commit_list_count(const struct commit_list *l);
5757
struct commit_list *commit_list_insert_by_date(struct commit *item,
5858
struct commit_list **list);
5959
void commit_list_sort_by_date(struct commit_list **list);
60+
void commit_list_reverse(struct commit_list **list_p);
6061

6162
void free_commit_list(struct commit_list *list);
6263

revision.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2054,11 +2054,13 @@ int prepare_revision_walk(struct rev_info *revs)
20542054
if (commit) {
20552055
if (!(commit->object.flags & SEEN)) {
20562056
commit->object.flags |= SEEN;
2057-
commit_list_insert_by_date(commit, &revs->commits);
2057+
commit_list_insert(commit, &revs->commits);
20582058
}
20592059
}
20602060
e++;
20612061
}
2062+
commit_list_reverse(&revs->commits);
2063+
commit_list_sort_by_date(&revs->commits);
20622064
if (!revs->leak_pending)
20632065
free(list);
20642066

0 commit comments

Comments
 (0)