{"thread":{"id":"20211","subject":"[PATCH 1/3] git branch: fix performance problem","startedAt":"2009-07-23T19:18:15Z","lastAt":"2009-07-23T19:20:48Z","messageCount":3,"participants":["Linus Torvalds"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"118600","messageId":"alpine.LFD.2.01.0907231216550.21520@localhost.localdomain","threadId":"20211","inReplyTo":null,"subject":"[PATCH 1/3] git branch: fix performance problem","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2009-07-23T19:18:15Z","receivedAt":"2009-07-23T19:18:15Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\nFrom: Linus Torvalds <torvalds@linux-foundation.org>\nDate: Thu, 23 Jul 2009 10:17:04 -0700\n\n'git branch' looks at _all_ the refs, and verifies them.  Which means that \nduring cold-cache situations with a slow disk (and lots of tags, for \nexample) it can take several very annoying seconds (7.5s according to a \nreport by Carlos R.  Mafra).\n\nThis avoids most of it by simply doing the filtering before looking up\nthe commits, by using the \"raw\" version of for_each_ref.\n\nReported-by: Carlos R. Mafra <crmafra2@gmail.com>\nSigned-off-by: Linus Torvalds <torvalds@linux-foundation.org>\n---\n\nOk, this is just a resend of the patches I've sent out, as a proper patch \nseries, with sign-offs etc.\n\n builtin-branch.c |   10 +++++-----\n 1 files changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 5687d60..54a89ff 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -240,6 +240,10 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags,\n \tif (ARRAY_SIZE(ref_kind) <= i)\n \t\treturn 0;\n \n+\t/* Don't add types the caller doesn't want */\n+\tif ((kind & ref_list->kinds) == 0)\n+\t\treturn 0;\n+\n \tcommit = lookup_commit_reference_gently(sha1, 1);\n \tif (!commit)\n \t\treturn error(\"branch '%s' does not point at a commit\", refname);\n@@ -248,10 +252,6 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags,\n \tif (!is_descendant_of(commit, ref_list->with_commit))\n \t\treturn 0;\n \n-\t/* Don't add types the caller doesn't want */\n-\tif ((kind & ref_list->kinds) == 0)\n-\t\treturn 0;\n-\n \tif (merge_filter != NO_FILTER)\n \t\tadd_pending_object(&ref_list->revs,\n \t\t\t\t   (struct object *)commit, refname);\n@@ -426,7 +426,7 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev, str\n \tref_list.with_commit = with_commit;\n \tif (merge_filter != NO_FILTER)\n \t\tinit_revisions(&ref_list.revs, NULL);\n-\tfor_each_ref(append_ref, &ref_list);\n+\tfor_each_rawref(append_ref, &ref_list);\n \tif (merge_filter != NO_FILTER) {\n \t\tstruct commit *filter;\n \t\tfilter = lookup_commit_reference_gently(merge_filter_ref, 0);\n-- \n1.6.4.rc1.2.gdf1f0\n"},{"id":"118601","messageId":"alpine.LFD.2.01.0907231218250.21520@localhost.localdomain","threadId":"20211","inReplyTo":"alpine.LFD.2.01.0907231216550.21520@localhost.localdomain","subject":"[PATCH 2/3] git branch: avoid unnecessary object lookups","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2009-07-23T19:18:56Z","receivedAt":"2009-07-23T19:18:56Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\nFrom: Linus Torvalds <torvalds@linux-foundation.org>\nDate: Thu, 23 Jul 2009 12:05:34 -0700\n\nThey can be expensive in the cold-cache case, so don't bother looking up\nthe commits for all branches unless we really need them for some reason.\n\nSigned-off-by: Linus Torvalds <torvalds@linux-foundation.org>\n---\n builtin-branch.c |   24 ++++++++++++++----------\n 1 files changed, 14 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 54a89ff..82c2cf0 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -191,7 +191,7 @@ struct ref_item {\n \n struct ref_list {\n \tstruct rev_info revs;\n-\tint index, alloc, maxwidth;\n+\tint index, alloc, maxwidth, verbose;\n \tstruct ref_item *list;\n \tstruct commit_list *with_commit;\n \tint kinds;\n@@ -244,17 +244,20 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags,\n \tif ((kind & ref_list->kinds) == 0)\n \t\treturn 0;\n \n-\tcommit = lookup_commit_reference_gently(sha1, 1);\n-\tif (!commit)\n-\t\treturn error(\"branch '%s' does not point at a commit\", refname);\n+\tcommit = NULL;\n+\tif (ref_list->verbose || ref_list->with_commit || merge_filter != NO_FILTER) {\n+\t\tcommit = lookup_commit_reference_gently(sha1, 1);\n+\t\tif (!commit)\n+\t\t\treturn error(\"branch '%s' does not point at a commit\", refname);\n \n-\t/* Filter with with_commit if specified */\n-\tif (!is_descendant_of(commit, ref_list->with_commit))\n-\t\treturn 0;\n+\t\t/* Filter with with_commit if specified */\n+\t\tif (!is_descendant_of(commit, ref_list->with_commit))\n+\t\t\treturn 0;\n \n-\tif (merge_filter != NO_FILTER)\n-\t\tadd_pending_object(&ref_list->revs,\n-\t\t\t\t   (struct object *)commit, refname);\n+\t\tif (merge_filter != NO_FILTER)\n+\t\t\tadd_pending_object(&ref_list->revs,\n+\t\t\t\t\t   (struct object *)commit, refname);\n+\t}\n \n \t/* Resize buffer */\n \tif (ref_list->index >= ref_list->alloc) {\n@@ -423,6 +426,7 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev, str\n \n \tmemset(&ref_list, 0, sizeof(ref_list));\n \tref_list.kinds = kinds;\n+\tref_list.verbose = verbose;\n \tref_list.with_commit = with_commit;\n \tif (merge_filter != NO_FILTER)\n \t\tinit_revisions(&ref_list.revs, NULL);\n-- \n1.6.4.rc1.2.gdf1f0\n"},{"id":"118602","messageId":"alpine.LFD.2.01.0907231218590.21520@localhost.localdomain","threadId":"20211","inReplyTo":"alpine.LFD.2.01.0907231218250.21520@localhost.localdomain","subject":"[PATCH 3/3] git branch: clean up detached branch handling","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2009-07-23T19:20:48Z","receivedAt":"2009-07-23T19:20:48Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\nFrom: Linus Torvalds <torvalds@linux-foundation.org>\nDate: Thu, 23 Jul 2009 12:13:48 -0700\n\nMake the 'show detached branch info' a routine of its own.  And in the\nprocess, avoid the object lookup that is unnecessary if the current\nbranch isn't detached.\n\nSigned-off-by: Linus Torvalds <torvalds@linux-foundation.org>\n---\n\nWith this series of three, 'git branch' now makes no object lookups at all \nfor the normal case of an attached branch and no fancy flags. \n\n builtin-branch.c |   38 +++++++++++++++++++++++---------------\n 1 files changed, 23 insertions(+), 15 deletions(-)\n\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 82c2cf0..1a03d5f 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -191,7 +191,7 @@ struct ref_item {\n \n struct ref_list {\n \tstruct rev_info revs;\n-\tint index, alloc, maxwidth, verbose;\n+\tint index, alloc, maxwidth, verbose, abbrev;\n \tstruct ref_item *list;\n \tstruct commit_list *with_commit;\n \tint kinds;\n@@ -418,15 +418,34 @@ static int calc_maxwidth(struct ref_list *refs)\n \treturn w;\n }\n \n+\n+static void show_detached(struct ref_list *ref_list)\n+{\n+\tstruct commit *head_commit = lookup_commit_reference_gently(head_sha1, 1);\n+\n+\tif (head_commit && is_descendant_of(head_commit, ref_list->with_commit)) {\n+\t\tstruct ref_item item;\n+\t\titem.name = xstrdup(\"(no branch)\");\n+\t\titem.len = strlen(item.name);\n+\t\titem.kind = REF_LOCAL_BRANCH;\n+\t\titem.dest = NULL;\n+\t\titem.commit = head_commit;\n+\t\tif (item.len > ref_list->maxwidth)\n+\t\t\tref_list->maxwidth = item.len;\n+\t\tprint_ref_item(&item, ref_list->maxwidth, ref_list->verbose, ref_list->abbrev, 1, \"\");\n+\t\tfree(item.name);\n+\t}\n+}\n+\n static void print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit)\n {\n \tint i;\n \tstruct ref_list ref_list;\n-\tstruct commit *head_commit = lookup_commit_reference_gently(head_sha1, 1);\n \n \tmemset(&ref_list, 0, sizeof(ref_list));\n \tref_list.kinds = kinds;\n \tref_list.verbose = verbose;\n+\tref_list.abbrev = abbrev;\n \tref_list.with_commit = with_commit;\n \tif (merge_filter != NO_FILTER)\n \t\tinit_revisions(&ref_list.revs, NULL);\n@@ -446,19 +465,8 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev, str\n \tqsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp);\n \n \tdetached = (detached && (kinds & REF_LOCAL_BRANCH));\n-\tif (detached && head_commit &&\n-\t    is_descendant_of(head_commit, with_commit)) {\n-\t\tstruct ref_item item;\n-\t\titem.name = xstrdup(\"(no branch)\");\n-\t\titem.len = strlen(item.name);\n-\t\titem.kind = REF_LOCAL_BRANCH;\n-\t\titem.dest = NULL;\n-\t\titem.commit = head_commit;\n-\t\tif (item.len > ref_list.maxwidth)\n-\t\t\tref_list.maxwidth = item.len;\n-\t\tprint_ref_item(&item, ref_list.maxwidth, verbose, abbrev, 1, \"\");\n-\t\tfree(item.name);\n-\t}\n+\tif (detached)\n+\t\tshow_detached(&ref_list);\n \n \tfor (i = 0; i < ref_list.index; i++) {\n \t\tint current = !detached &&\n-- \n1.6.4.rc1.2.gdf1f0\n"}]}