{"thread":{"id":"35691","subject":"[PATCH] improve git svn performance Hi, I am trying to improve git svn's performance according to some profiling data.As the data showed,_rev_list subroutine and rebuild subroutine are consuming a large proportion of time.So I improve _rev_list's performance by memoize its results,and avoid subprocess invocation by memoize rebuild subroutine's key data.Here's my patch:","startedAt":"2014-01-20T04:36:19Z","lastAt":"2014-01-20T04:36:19Z","messageCount":1,"participants":["manjian2006@gmail.com"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"233395","messageId":"1390192579-3635-1-git-send-email-manjian2006@gmail.com","threadId":"35691","inReplyTo":null,"subject":"[PATCH] improve git svn performance Hi, I am trying to improve git svn's performance according to some profiling data.As the data showed,_rev_list subroutine and rebuild subroutine are consuming a large proportion of time.So I improve _rev_list's performance by memoize its results,and avoid subprocess invocation by memoize rebuild subroutine's key data.Here's my patch:","fromName":"","fromEmail":"manjian2006@gmail.com","sentAt":"2014-01-20T04:36:19Z","receivedAt":"2014-01-20T04:36:19Z","isPatch":true,"sender":{"key":"manjian2006@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5935381?v=4"},"body":"From: linzj <linzj@ucweb.com>\n\n---\n perl/Git/SVN.pm | 63 ++++++++++++++++++++++++++++++++++++++++++++-------------\n 1 file changed, 49 insertions(+), 14 deletions(-)\n\ndiff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm\nindex 5273ee8..3cd1c8f 100644\n--- a/perl/Git/SVN.pm\n+++ b/perl/Git/SVN.pm\n@@ -1599,27 +1599,36 @@ sub tie_for_persistent_memoization {\n \t\tmy %lookup_svn_merge_cache;\n \t\tmy %check_cherry_pick_cache;\n \t\tmy %has_no_changes_cache;\n+\t\tmy %_rev_list_cache;\n \n \t\ttie_for_persistent_memoization(\\%lookup_svn_merge_cache,\n-\t\t    \"$cache_path/lookup_svn_merge\");\n+\t\t\t\t\"$cache_path/lookup_svn_merge\");\n \t\tmemoize 'lookup_svn_merge',\n-\t\t\tSCALAR_CACHE => 'FAULT',\n-\t\t\tLIST_CACHE => ['HASH' => \\%lookup_svn_merge_cache],\n-\t\t;\n+\t\t\t\tSCALAR_CACHE => 'FAULT',\n+\t\t\t\tLIST_CACHE => ['HASH' => \\%lookup_svn_merge_cache],\n+\t\t\t\t;\n \n \t\ttie_for_persistent_memoization(\\%check_cherry_pick_cache,\n-\t\t    \"$cache_path/check_cherry_pick\");\n+\t\t\t\t\"$cache_path/check_cherry_pick\");\n \t\tmemoize 'check_cherry_pick',\n-\t\t\tSCALAR_CACHE => 'FAULT',\n-\t\t\tLIST_CACHE => ['HASH' => \\%check_cherry_pick_cache],\n-\t\t;\n+\t\t\t\tSCALAR_CACHE => 'FAULT',\n+\t\t\t\tLIST_CACHE => ['HASH' => \\%check_cherry_pick_cache],\n+\t\t\t\t;\n \n \t\ttie_for_persistent_memoization(\\%has_no_changes_cache,\n-\t\t    \"$cache_path/has_no_changes\");\n+\t\t\t\t\"$cache_path/has_no_changes\");\n \t\tmemoize 'has_no_changes',\n-\t\t\tSCALAR_CACHE => ['HASH' => \\%has_no_changes_cache],\n-\t\t\tLIST_CACHE => 'FAULT',\n-\t\t;\n+\t\t\t\tSCALAR_CACHE => ['HASH' => \\%has_no_changes_cache],\n+\t\t\t\tLIST_CACHE => 'FAULT',\n+\t\t\t\t;\n+\n+\t\ttie_for_persistent_memoization(\\%_rev_list_cache,\n+\t\t\t\t\"$cache_path/_rev_list\");\n+\t\tmemoize '_rev_list',\n+\t\t\t\tSCALAR_CACHE => 'FAULT',\n+\t\t\t\tLIST_CACHE => ['HASH' => \\%_rev_list_cache],\n+\t\t\t\t;\n+\n \t}\n \n \tsub unmemoize_svn_mergeinfo_functions {\n@@ -1629,6 +1638,7 @@ sub tie_for_persistent_memoization {\n \t\tMemoize::unmemoize 'lookup_svn_merge';\n \t\tMemoize::unmemoize 'check_cherry_pick';\n \t\tMemoize::unmemoize 'has_no_changes';\n+\t\tMemoize::unmemoize '_rev_list';\n \t}\n \n \tsub clear_memoized_mergeinfo_caches {\n@@ -1959,11 +1969,25 @@ sub rebuild_from_rev_db {\n \tunlink $path or croak \"unlink: $!\";\n }\n \n+#define a global associate map to record rebuild status\n+my %rebuildStatus;\n+#define a global associate map to record rebuild verify status\n+my %rebuildVerifyStatus;\n+\n sub rebuild {\n \tmy ($self) = @_;\n \tmy $map_path = $self->map_path;\n \tmy $partial = (-e $map_path && ! -z $map_path);\n-\treturn unless ::verify_ref($self->refname.'^0');\n+    my $verifyKey = $self->refname.'^0';\n+    if (! exists $rebuildVerifyStatus{$verifyKey} || ! defined $rebuildVerifyStatus{$verifyKey} ) {\n+        my $verifyResult = ::verify_ref($verifyKey);\n+        if ($verifyResult) {\n+            $rebuildVerifyStatus{$verifyKey} = 1;\n+        }\n+    }\n+    if (! exists $rebuildVerifyStatus{$verifyKey}) {\n+        return;\n+    }\n \tif (!$partial && ($self->use_svm_props || $self->no_metadata)) {\n \t\tmy $rev_db = $self->rev_db_path;\n \t\t$self->rebuild_from_rev_db($rev_db);\n@@ -1977,10 +2001,21 @@ sub rebuild {\n \tprint \"Rebuilding $map_path ...\\n\" if (!$partial);\n \tmy ($base_rev, $head) = ($partial ? $self->rev_map_max_norebuild(1) :\n \t\t(undef, undef));\n+    my $keyValue = ($head ? \"$head..\" : \"\") . $self->refname;\n+    if (exists $rebuildStatus{$keyValue}) {\n+        print \"Done rebuilding $map_path\\n\" if (!$partial || !$head);\n+        my $rev_db_path = $self->rev_db_path;\n+        if (-f $self->rev_db_path) {\n+            unlink $self->rev_db_path or croak \"unlink: $!\";\n+        }\n+        $self->unlink_rev_db_symlink;\n+\t\treturn;\n+    }\n \tmy ($log, $ctx) =\n \t    command_output_pipe(qw/rev-list --pretty=raw --reverse/,\n-\t\t\t\t($head ? \"$head..\" : \"\") . $self->refname,\n+\t\t\t    $keyValue,\t\n \t\t\t\t'--');\n+    $rebuildStatus{$keyValue} = 1;\n \tmy $metadata_url = $self->metadata_url;\n \tremove_username($metadata_url);\n \tmy $svn_uuid = $self->rewrite_uuid || $self->ra_uuid;\n-- \n1.8.3.2\n"}]}