path: root/rev-list.c
diff options
authorLinus Torvalds <>2005-10-19 01:29:17 (GMT)
committerJunio C Hamano <>2005-10-19 01:41:28 (GMT)
commitfe5f51ce277df00cb01dfc984dba1e7128718e41 (patch)
treec358e2c3855b9a35a4685032d7fba2db65c0ecc4 /rev-list.c
parent3e04c62daab0a8481f907c30414ed246f284a1d9 (diff)
Optimize common case of git-rev-list
I took a look at webgit, and it looks like at least for the "projects" page, the most common operation ends up being basically git-rev-list --header --parents --max-count=1 HEAD Now, the thing is, the way "git-rev-list" works, it always keeps on popping the parents and parsing them in order to build the list of parents, and it turns out that even though we just want a single commit, git-rev-list will invariably look up _three_ generations of commits. It will parse: - the commit we want (it obviously needs this) - it's parent(s) as part of the "pop_most_recent_commit()" logic - it will then pop one of the parents before it notices that it doesn't need any more - and as part of popping the parent, it will parse the grandparent (again due to "pop_most_recent_commit()". Now, I've strace'd it, and it really is pretty efficient on the whole, but if things aren't nicely cached, and with long-latency IO, doing those two extra objects (at a minimum - if the parent is a merge it will be more) is just wasted time, and potentially a lot of it. So here's a quick special-case for the trivial case of "just one commit, and no date-limits or other special rules". Signed-off-by: Linus Torvalds <> Signed-off-by: Junio C Hamano <>
Diffstat (limited to 'rev-list.c')
1 files changed, 5 insertions, 0 deletions
diff --git a/rev-list.c b/rev-list.c
index c60aa72..3a32e40 100644
--- a/rev-list.c
+++ b/rev-list.c
@@ -624,6 +624,11 @@ int main(int argc, char **argv)
if (!merge_order) {
+ if (list && !limited && max_count == 1 &&
+ !tag_objects && !tree_objects && !blob_objects) {
+ show_commit(list->item);
+ return 0;
+ }
if (limited)
list = limit_list(list);
if (topo_order)