git-svn: lazy load some modules
authorEric Wong <normalperson@yhbt.net>
Thu, 15 Jan 2015 08:54:22 +0000 (08:54 +0000)
committerEric Wong <normalperson@yhbt.net>
Thu, 26 Feb 2015 20:19:21 +0000 (20:19 +0000)
We can delay loading some modules until we need them for uncommon
code paths. For example, persistent memoization is not often
needed, so we can avoid loading the modules for it until we
encounter svn::mergeinfo during fetch.

This gives a tiny reduction in syscalls (from 15641 to 15305) when
running "git svn info" and counting via "strace -fc". Further,
more invasive work will be needed to noticeably improve performance.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
git-svn.perl
perl/Git/SVN.pm
perl/Git/SVN/Editor.pm
perl/Git/SVN/Fetcher.pm
perl/Git/SVN/Ra.pm
index 32d109ebdf89399ac0d834cc98393324dfca7850..36f7240c99249198512689ffecdd9c95f06b8eff 100755 (executable)
 $VERSION = '@@GIT_VERSION@@';
 
 use Carp qw/croak/;
-use Digest::MD5;
-use IO::File qw//;
 use File::Basename qw/dirname basename/;
 use File::Path qw/mkpath/;
 use File::Spec;
-use File::Find;
 use Getopt::Long qw/:config gnu_getopt no_ignore_case auto_abbrev/;
-use IPC::Open3;
 use Memoize;
 
 use Git::SVN;
@@ -298,7 +294,6 @@ sub _req_svn {
                {} ],
 );
 
-use Term::ReadLine;
 package FakeTerm;
 sub new {
        my ($class, $reason) = @_;
@@ -313,6 +308,7 @@ package main;
 my $term;
 sub term_init {
        $term = eval {
+               require Term::ReadLine;
                $ENV{"GIT_SVN_NOTTY"}
                        ? new Term::ReadLine 'git-svn', \*STDIN, \*STDOUT
                        : new Term::ReadLine 'git-svn';
@@ -1173,6 +1169,7 @@ sub cmd_branch {
        }
 
        ::_req_svn();
+       require SVN::Client;
 
        my $ctx = SVN::Client->new(
                config => SVN::Core::config_get_config(
@@ -1693,11 +1690,13 @@ sub cmd_reset {
 }
 
 sub cmd_gc {
+       require File::Find;
        if (!can_compress()) {
                warn "Compress::Zlib could not be found; unhandled.log " .
                     "files will not be compressed.\n";
        }
-       find({ wanted => \&gc_directory, no_chdir => 1}, "$ENV{GIT_DIR}/svn");
+       File::Find::find({ wanted => \&gc_directory, no_chdir => 1},
+                        "$ENV{GIT_DIR}/svn");
 }
 
 ########################### utility functions #########################
@@ -2122,6 +2121,7 @@ sub find_file_type_and_diff_status {
 sub md5sum {
        my $arg = shift;
        my $ref = ref $arg;
+       require Digest::MD5;
        my $md5 = Digest::MD5->new();
         if ($ref eq 'GLOB' || $ref eq 'IO::File' || $ref eq 'File::Temp') {
                $md5->addfile($arg) or croak $!;
@@ -2148,6 +2148,7 @@ sub gc_directory {
                        $gz->gzwrite($str) or
                                die "Unable to write: ".$gz->gzerror()."!\n";
                }
+               no warnings 'once'; # $File::Find::name would warn
                unlink $_ or die "unlink $File::Find::name: $!\n";
        } elsif (-f $_ && basename($_) eq "index") {
                unlink $_ or die "unlink $_: $!\n";
index 8e4af7153eb8a8957bd4172e0c044c1bfc748ddb..afa562c8b9f8129e76b2cd7c9568ba1b3dfa06df 100644 (file)
@@ -9,10 +9,8 @@ package Git::SVN;
            $_use_log_author $_add_author_from $_localtime/;
 use Carp qw/croak/;
 use File::Path qw/mkpath/;
-use File::Copy qw/copy/;
 use IPC::Open3;
 use Memoize;  # core since 5.8.0, Jul 2002
-use Memoize::Storable;
 use POSIX qw(:signal_h);
 
 use Git qw(
@@ -32,11 +30,7 @@ package Git::SVN;
        add_path_to_url
 );
 
-my $can_use_yaml;
-BEGIN {
-       $can_use_yaml = eval { require Git::SVN::Memoize::YAML; 1};
-}
-
+my $memo_backend;
 our $_follow_parent  = 1;
 our $_minimize_url   = 'unset';
 our $default_repo_id = 'svn';
@@ -1578,7 +1572,16 @@ sub tie_for_persistent_memoization {
        my $hash = shift;
        my $path = shift;
 
-       if ($can_use_yaml) {
+       unless ($memo_backend) {
+               if (eval { require Git::SVN::Memoize::YAML; 1}) {
+                       $memo_backend = 1;
+               } else {
+                       require Memoize::Storable;
+                       $memo_backend = -1;
+               }
+       }
+
+       if ($memo_backend > 0) {
                tie %$hash => 'Git::SVN::Memoize::YAML', "$path.yaml";
        } else {
                tie %$hash => 'Memoize::Storable', "$path.db", 'nstore';
@@ -2188,8 +2191,9 @@ sub rev_map_set {
        # both of these options make our .rev_db file very, very important
        # and we can't afford to lose it because rebuild() won't work
        if ($self->use_svm_props || $self->no_metadata) {
+               require File::Copy;
                $sync = 1;
-               copy($db, $db_lock) or die "rev_map_set(@_): ",
+               File::Copy::copy($db, $db_lock) or die "rev_map_set(@_): ",
                                           "Failed to copy: ",
                                           "$db => $db_lock ($!)\n";
        } else {
index 4088f13e723a51a6e1cee0c616a7c279a780461d..c50176eec9418c50e5c63921c24e76a87b6123ab 100644 (file)
@@ -5,7 +5,6 @@ package Git::SVN::Editor;
 use SVN::Core;
 use SVN::Delta;
 use Carp qw/croak/;
-use IO::File;
 use Git qw/command command_oneline command_noisy command_output_pipe
            command_input_pipe command_close_pipe
            command_bidi_pipe command_close_bidi_pipe/;
@@ -586,7 +585,7 @@ =head1 DESCRIPTION
 =head1 DEPENDENCIES
 
 Subversion perl bindings,
-the core L<Carp> and L<IO::File> modules,
+the core L<Carp> module,
 and git's L<Git> helper module.
 
 C<Git::SVN::Editor> has not been tested using callers other than
index 10edb27732f439e5290a7b354efefeb10d219669..6b9c6e01386fee3756298fcb4d580a478158302f 100644 (file)
@@ -7,7 +7,6 @@ package Git::SVN::Fetcher;
 use SVN::Delta;
 use Carp qw/croak/;
 use File::Basename qw/dirname/;
-use IO::File qw//;
 use Git qw/command command_oneline command_noisy command_output_pipe
            command_input_pipe command_close_pipe
            command_bidi_pipe command_close_bidi_pipe/;
@@ -600,7 +599,7 @@ =head1 DESCRIPTION
 =head1 DEPENDENCIES
 
 L<SVN::Delta> from the Subversion perl bindings,
-the core L<Carp>, L<File::Basename>, and L<IO::File> modules,
+the core L<Carp> and L<File::Basename> modules,
 and git's L<Git> helper module.
 
 C<Git::SVN::Fetcher> has not been tested using callers other than
index 622535e21760f9fd5c6b63f97d41b48be9c04db6..cf36b9d3cdde67f03f147d596f8f277ea11ba302 100644 (file)
@@ -3,7 +3,6 @@ package Git::SVN::Ra;
 use strict;
 use warnings;
 use Memoize;
-use SVN::Client;
 use Git::SVN::Utils qw(
        canonicalize_url
        canonicalize_path
@@ -42,6 +41,7 @@ END
 }
 
 sub _auth_providers () {
+       require SVN::Client;
        my @rv = (
          SVN::Client::get_simple_provider(),
          SVN::Client::get_ssl_server_trust_file_provider(),
@@ -247,7 +247,10 @@ sub get_log {
        $ret;
 }
 
+# uncommon, only for ancient SVN (<= 1.4.2)
 sub trees_match {
+       require IO::File;
+       require SVN::Client;
        my ($self, $url1, $rev1, $url2, $rev2) = @_;
        my $ctx = SVN::Client->new(auth => _auth_providers);
        my $out = IO::File->new_tmpfile;