contacts: reduce git-blame invocations
authorEric Sunshine <sunshine@sunshineco.com>
Fri, 9 Aug 2013 21:39:56 +0000 (17:39 -0400)
committerJunio C Hamano <gitster@pobox.com>
Tue, 13 Aug 2013 16:09:03 +0000 (09:09 -0700)
git-contacts invokes git-blame once for each patch hunk it encounters.
No attempt is made to consolidate invocations for multiple hunks
referencing the same file at the same revision. This can become
expensive quickly.

Reduce the number of git-blame invocations by taking advantage of the
ability to specify multiple -L ranges for a single invocation.

Without this patch, on a randomly chosen range of commits:

% time git-contacts 25fba78d36be6297^..23c339c0f262aad2 >/dev/null
real 0m6.142s
user 0m5.429s
sys 0m0.356s

With this patch:

% time git-contacts 25fba78d36be6297^..23c339c0f262aad2 >/dev/null
real 0m2.285s
user 0m2.093s
sys 0m0.165s

Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
contrib/contacts/git-contacts
index b4d3526a4666bb737db56f64771fcddf3e7afca7..fb6429b64be3cf7011ce69950987a8b328e0e758 100755 (executable)
@@ -59,9 +59,11 @@ sub import_commits {
 }
 
 sub get_blame {
-       my ($commits, $source, $start, $len, $from) = @_;
+       my ($commits, $source, $from, $ranges) = @_;
+       return unless @$ranges;
        open my $f, '-|',
-               qw(git blame --porcelain -C), '-L', "$start,+$len",
+               qw(git blame --porcelain -C),
+               map({"-L$_->[0],+$_->[1]"} @$ranges),
                '--since', $since, "$from^", '--', $source or die;
        while (<$f>) {
                if (/^([0-9a-f]{40}) \d+ \d+ \d+$/) {
@@ -78,10 +80,7 @@ sub blame_sources {
        my ($sources, $commits) = @_;
        for my $s (keys %$sources) {
                for my $id (keys %{$sources->{$s}}) {
-                       for my $range (@{$sources->{$s}{$id}}) {
-                               get_blame($commits, $s,
-                                         $range->[0], $range->[1], $id);
-                       }
+                       get_blame($commits, $s, $id, $sources->{$s}{$id});
                }
        }
 }