git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 7/9] send-email: lazily load modules for a big speedup

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
May 12, 2021, 13:48 UTC
Message-ID
<patch-7.9-55a0b07062-20210512T132955Z-avarab@gmail.com>
In-Reply-To
<cover-0.9-0000000000-20210512T132955Z-avarab@gmail.com>

Optimize the time git-send-email takes to do even the simplest of things (such as serving up "-h") from around ~150ms to ~80ms-~90ms by lazily loading the modules it requires.

Before this change Devel::TraceUse would report 99/97 used modules under NO_GETTEXT=[|Y], respectively. Now it's 52/37. It now takes ~15s to run t9001-send-email.sh, down from ~20s.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 git-send-email.perl | 70 +++++++++++++++++++++++++--------------------
 1 file changed, 39 insertions(+), 31 deletions(-)
diff --git a/git-send-email.perl b/git-send-email.perl
index f9c780ceed..907dc1425f 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -19,20 +19,10 @@
 use 5.008;
 use strict;
 use warnings;
-use POSIX qw/strftime/;
-use Term::ReadLine;
 use Getopt::Long;
-use Text::ParseWords;
-use Term::ANSIColor;
-use File::Temp qw/ tempdir tempfile /;
-use File::Spec::Functions qw(catdir catfile);
 use Git::LoadCPAN::Error qw(:try);
-use Cwd qw(abs_path cwd);
 use Git;
 use Git::I18N;
-use Net::Domain ();
-use Net::SMTP ();
-use Git::LoadCPAN::Mail::Address;
 
 Getopt::Long::Configure qw/ pass_through /;
 
@@ -166,7 +156,6 @@ sub format_2822_time {
 		       );
 }
 
-my $have_email_valid = eval { require Email::Valid; 1 };
 my $smtp;
 my $auth;
 my $num_sent = 0;
@@ -192,14 +181,6 @@ sub format_2822_time {
 
 my $repo = eval { Git->repository() };
 my @repo = $repo ? ($repo) : ();
-my $term = eval {
-	$ENV{"GIT_SEND_EMAIL_NOTTY"}
-		? Term::ReadLine->new('git-send-email', \*STDIN, \*STDOUT)
-		: Term::ReadLine->new('git-send-email');
-};
-if ($@) {
-	$term = FakeTerm->new("$@: going non-interactive");
-}
 
 # Behavior modification variables
 my ($quiet, $dry_run) = (0, 0);
@@ -309,9 +290,10 @@ sub do_edit {
 
 # Handle Uncouth Termination
 sub signal_handler {
+	require Term::ANSIColor;
 
 	# Make text normal
-	print color("reset"), "\n";
+	print Term::ANSIColor::color("reset"), "\n";
 
 	# SMTP password masked
 	system "stty echo";
@@ -574,11 +556,13 @@ sub read_config {
 }
 
 sub parse_address_line {
+	require Git::LoadCPAN::Mail::Address;
 	return map { $_->format } Mail::Address->parse($_[0]);
 }
 
 sub split_addrs {
-	return quotewords('\s*,\s*', 1, @_);
+	require Text::ParseWords;
+	return Text::ParseWords::quotewords('\s*,\s*', 1, @_);
 }
 
 my %aliases;
@@ -627,10 +611,11 @@ sub parse_sendmail_aliases {
 			s/\\"/"/g foreach @addr;
 			$aliases{$alias} = \@addr
 		}}},
-	mailrc => sub { my $fh = shift; while (<$fh>) {
+	mailrc => sub {	my $fh = shift; while (<$fh>) {
 		if (/^alias\s+(\S+)\s+(.*?)\s*$/) {
+			require Text::ParseWords;
 			# spaces delimit multiple addresses
-			$aliases{$1} = [ quotewords('\s+', 0, $2) ];
+			$aliases{$1} = [ Text::ParseWords::quotewords('\s+', 0, $2) ];
 		}}},
 	pine => sub { my $fh = shift; my $f='\t[^\t]*';
 	        for (my $x = ''; defined($x); $x = $_) {
@@ -702,7 +687,8 @@ sub is_format_patch_arg {
 		opendir my $dh, $f
 			or die sprintf(__("Failed to opendir %s: %s"), $f, $!);
 
-		push @files, grep { -f $_ } map { catfile($f, $_) }
+		require File::Spec;
+		push @files, grep { -f $_ } map { File::Spec->catfile($f, $_) }
 				sort readdir $dh;
 		closedir $dh;
 	} elsif ((-f $f or -p $f) and !is_format_patch_arg($f)) {
@@ -715,7 +701,8 @@ sub is_format_patch_arg {
 if (@rev_list_opts) {
 	die __("Cannot run git format-patch from outside a repository\n")
 		unless $repo;
-	push @files, $repo->command('format-patch', '-o', tempdir(CLEANUP => 1), @rev_list_opts);
+	require File::Temp;
+	push @files, $repo->command('format-patch', '-o', File::Temp::tempdir(CLEANUP => 1), @rev_list_opts);
 }
 
 @files = handle_backup_files(@files);
@@ -752,9 +739,10 @@ sub get_patch_subject {
 if ($compose) {
 	# Note that this does not need to be secure, but we will make a small
 	# effort to have it be unique
+	require File::Temp;
 	$compose_filename = ($repo ?
-		tempfile(".gitsendemail.msg.XXXXXX", DIR => $repo->repo_path()) :
-		tempfile(".gitsendemail.msg.XXXXXX", DIR => "."))[1];
+		File::Temp::tempfile(".gitsendemail.msg.XXXXXX", DIR => $repo->repo_path()) :
+		File::Temp::tempfile(".gitsendemail.msg.XXXXXX", DIR => "."))[1];
 	open my $c, ">", $compose_filename
 		or die sprintf(__("Failed to open for writing %s: %s"), $compose_filename, $!);
 
@@ -861,6 +849,19 @@ sub get_patch_subject {
 	do_edit(@files);
 }
 
+sub term {
+	my $term = eval {
+		require Term::ReadLine;
+		$ENV{"GIT_SEND_EMAIL_NOTTY"}
+			? Term::ReadLine->new('git-send-email', \*STDIN, \*STDOUT)
+			: Term::ReadLine->new('git-send-email');
+	};
+	if ($@) {
+		$term = FakeTerm->new("$@: going non-interactive");
+	}
+	return $term;
+}
+
 sub ask {
 	my ($prompt, %arg) = @_;
 	my $valid_re = $arg{valid_re};
@@ -868,6 +869,7 @@ sub ask {
 	my $confirm_only = $arg{confirm_only};
 	my $resp;
 	my $i = 0;
+	my $term = term();
 	return defined $default ? $default : undef
 		unless defined $term->IN and defined fileno($term->IN) and
 		       defined $term->OUT and defined fileno($term->OUT);
@@ -1048,6 +1050,7 @@ sub extract_valid_address {
 	return $address if ($address =~ /^($local_part_regexp)$/);
 
 	$address =~ s/^\s*<(.*)>\s*$/$1/;
+	my $have_email_valid = eval { require Email::Valid; 1 };
 	if ($have_email_valid) {
 		return scalar Email::Valid->address($address);
 	}
@@ -1107,7 +1110,8 @@ sub validate_address_list {
 sub make_message_id {
 	my $uniq;
 	if (!defined $message_id_stamp) {
-		$message_id_stamp = strftime("%Y%m%d%H%M%S.$$", gmtime(time));
+		require POSIX;
+		$message_id_stamp = POSIX::strftime("%Y%m%d%H%M%S.$$", gmtime(time));
 		$message_id_serial = 0;
 	}
 	$message_id_serial++;
@@ -1277,6 +1281,7 @@ sub valid_fqdn {
 sub maildomain_net {
 	my $maildomain;
 
+	require Net::Domain;
 	my $domain = Net::Domain::domainname();
 	$maildomain = $domain if valid_fqdn($domain);
 
@@ -1287,6 +1292,7 @@ sub maildomain_mta {
 	my $maildomain;
 
 	for my $host (qw(mailhost localhost)) {
+		require Net::SMTP;
 		my $smtp = Net::SMTP->new($host);
 		if (defined $smtp) {
 			my $domain = $smtp->domain;
@@ -1965,13 +1971,15 @@ sub validate_patch {
 	my ($fn, $xfer_encoding) = @_;
 
 	if ($repo) {
-		my $validate_hook = catfile($repo->hooks_path(),
+		require File::Spec;
+		my $validate_hook = File::Spec->catfile($repo->hooks_path(),
 					    'sendemail-validate');
 		my $hook_error;
 		if (-x $validate_hook) {
-			my $target = abs_path($fn);
+			require Cwd;
+			my $target = Cwd::abs_path($fn);
 			# The hook needs a correct cwd and GIT_DIR.
-			my $cwd_save = cwd();
+			my $cwd_save = Cwd::cwd();
 			chdir($repo->wc_path() or $repo->repo_path())
 				or die("chdir: $!");
 			local $ENV{"GIT_DIR"} = $repo->repo_path();
-- 
2.31.1.909.g789bb6d90e
Previous: Ævar Arnfjörð BjarmasonNext: Ævar Arnfjörð Bjarmason
Message 10 of 108 in “send-email: various optimizations to speed up by >2x”
  1. 0/9 send-email: various optimizations to speed up by >2xÆvar Arnfjörð Bjarmason, May 12, 2021
  2. 1/9 send-email: remove non-working support for "sendemail.smtpssl"Ævar Arnfjörð Bjarmason, May 12, 2021
  3. Đoàn Trần Công DanhMay 12, 2021
  4. 2/9 send-email: refactor sendemail.smtpencryption config parsingÆvar Arnfjörð Bjarmason, May 12, 2021
  5. 3/9 send-email: lazily load config for a big speedupÆvar Arnfjörð Bjarmason, May 12, 2021
  6. 4/9 send-email: lazily shell out to "git var"Ævar Arnfjörð Bjarmason, May 12, 2021
  7. 5/9 send-email: use function syntax instead of barewordsÆvar Arnfjörð Bjarmason, May 12, 2021
  8. Jeff KingMay 12, 2021
  9. 6/9 send-email: get rid of indirect object syntaxÆvar Arnfjörð Bjarmason, May 12, 2021
  10. 7/9 send-email: lazily load modules for a big speedupÆvar Arnfjörð Bjarmason, May 12, 2021
  11. 8/9 perl: lazily load some common Git.pm setup codeÆvar Arnfjörð Bjarmason, May 12, 2021
  12. Eric WongMay 12, 2021
  13. 9/9 send-email: move trivial config handling to PerlÆvar Arnfjörð Bjarmason, May 12, 2021
  14. Eric SunshineMay 12, 2021
  15. Jeff KingMay 12, 2021
  16. Felipe ContrerasMay 13, 2021
  17. Jeff KingMay 13, 2021
  18. Felipe ContrerasMay 13, 2021
  19. Ævar Arnfjörð BjarmasonMay 13, 2021
  20. Ævar Arnfjörð BjarmasonMay 13, 2021
  21. Eric WongMay 12, 2021
  22. Jeff KingMay 12, 2021
  23. Jeff KingMay 12, 2021
  24. Ævar Arnfjörð BjarmasonMay 13, 2021
  25. Jeff KingMay 13, 2021
  26. 00/10 send-email: various optimizations to speed up by >2xÆvar Arnfjörð Bjarmason, May 20, 2021
  27. 01/10 send-email: remove non-working support for "sendemail.smtpssl"Ævar Arnfjörð Bjarmason, May 20, 2021
  28. 02/10 send-email: refactor sendemail.smtpencryption config parsingÆvar Arnfjörð Bjarmason, May 20, 2021
  29. 03/10 send-email: lazily load config for a big speedupÆvar Arnfjörð Bjarmason, May 20, 2021
  30. 04/10 send-email: lazily shell out to "git var"Ævar Arnfjörð Bjarmason, May 20, 2021
  31. 05/10 send-email: use function syntax instead of barewordsÆvar Arnfjörð Bjarmason, May 20, 2021
  32. 06/10 send-email: get rid of indirect object syntaxÆvar Arnfjörð Bjarmason, May 20, 2021
  33. 08/10 perl: lazily load some common Git.pm setup codeÆvar Arnfjörð Bjarmason, May 20, 2021
  34. 07/10 send-email: lazily load modules for a big speedupÆvar Arnfjörð Bjarmason, May 20, 2021
  35. 10/10 perl: nano-optimize by replacing Cwd::cwd() with Cwd::getcwd()Ævar Arnfjörð Bjarmason, May 20, 2021
  36. 09/10 send-email: move trivial config handling to PerlÆvar Arnfjörð Bjarmason, May 20, 2021
  37. Jeff KingMay 20, 2021
  38. Junio C HamanoMay 20, 2021
  39. Ævar Arnfjörð BjarmasonMay 21, 2021
  40. Junio C HamanoMay 21, 2021
  41. Jeff KingMay 21, 2021
  42. Ævar Arnfjörð BjarmasonMay 21, 2021
  43. Jeff KingMay 21, 2021
  44. Felipe ContrerasMay 28, 2021
  45. Ævar Arnfjörð BjarmasonMay 29, 2021
  46. Felipe ContrerasMay 29, 2021
  47. Ævar Arnfjörð BjarmasonMay 30, 2021
  48. Felipe ContrerasMay 30, 2021
  49. Felipe ContrerasMay 28, 2021
  50. 00/13 send-email: various optimizations to speed up by >2xÆvar Arnfjörð Bjarmason, May 23, 2021
  51. 01/13 send-email tests: support GIT_TEST_PERL_FATAL_WARNINGS=trueÆvar Arnfjörð Bjarmason, May 23, 2021
  52. 02/13 send-email tests: test for boolean variables without a valueÆvar Arnfjörð Bjarmason, May 23, 2021
  53. 03/13 send-email: remove non-working support for "sendemail.smtpssl"Ævar Arnfjörð Bjarmason, May 23, 2021
  54. 04/13 send-email: refactor sendemail.smtpencryption config parsingÆvar Arnfjörð Bjarmason, May 23, 2021
  55. 05/13 send-email: copy "config_regxp" into git-send-email.perlÆvar Arnfjörð Bjarmason, May 23, 2021
  56. 06/13 send-email: lazily load config for a big speedupÆvar Arnfjörð Bjarmason, May 23, 2021
  57. 07/13 send-email: lazily shell out to "git var"Ævar Arnfjörð Bjarmason, May 23, 2021
  58. 09/13 send-email: get rid of indirect object syntaxÆvar Arnfjörð Bjarmason, May 23, 2021
  59. 08/13 send-email: use function syntax instead of barewordsÆvar Arnfjörð Bjarmason, May 23, 2021
  60. 10/13 send-email: lazily load modules for a big speedupÆvar Arnfjörð Bjarmason, May 23, 2021
  61. 11/13 perl: lazily load some common Git.pm setup codeÆvar Arnfjörð Bjarmason, May 23, 2021
  62. 12/13 send-email: move trivial config handling to PerlÆvar Arnfjörð Bjarmason, May 23, 2021
  63. 13/13 perl: nano-optimize by replacing Cwd::cwd() with Cwd::getcwd()Ævar Arnfjörð Bjarmason, May 23, 2021
  64. Junio C HamanoMay 24, 2021
  65. 00/13 send-email: various optimizations to speed up by >2xÆvar Arnfjörð Bjarmason, May 24, 2021
  66. 01/13 send-email tests: support GIT_TEST_PERL_FATAL_WARNINGS=trueÆvar Arnfjörð Bjarmason, May 24, 2021
  67. 02/13 send-email tests: test for boolean variables without a valueÆvar Arnfjörð Bjarmason, May 24, 2021
  68. 03/13 send-email: remove non-working support for "sendemail.smtpssl"Ævar Arnfjörð Bjarmason, May 24, 2021
  69. 04/13 send-email: refactor sendemail.smtpencryption config parsingÆvar Arnfjörð Bjarmason, May 24, 2021
  70. 07/13 send-email: lazily shell out to "git var"Ævar Arnfjörð Bjarmason, May 24, 2021
  71. 06/13 send-email: lazily load config for a big speedupÆvar Arnfjörð Bjarmason, May 24, 2021
  72. 05/13 send-email: copy "config_regxp" into git-send-email.perlÆvar Arnfjörð Bjarmason, May 24, 2021
  73. 09/13 send-email: get rid of indirect object syntaxÆvar Arnfjörð Bjarmason, May 24, 2021
  74. 10/13 send-email: lazily load modules for a big speedupÆvar Arnfjörð Bjarmason, May 24, 2021
  75. Junio C HamanoMay 27, 2021
  76. Ævar Arnfjörð BjarmasonMay 27, 2021
  77. 11/13 perl: lazily load some common Git.pm setup codeÆvar Arnfjörð Bjarmason, May 24, 2021
  78. 12/13 send-email: move trivial config handling to PerlÆvar Arnfjörð Bjarmason, May 24, 2021
  79. Jeff KingMay 27, 2021
  80. 08/13 send-email: use function syntax instead of barewordsÆvar Arnfjörð Bjarmason, May 24, 2021
  81. 13/13 perl: nano-optimize by replacing Cwd::cwd() with Cwd::getcwd()Ævar Arnfjörð Bjarmason, May 24, 2021
  82. Jeff KingMay 27, 2021
  83. 00/13 send-email: various optimizations to speed up by >2xÆvar Arnfjörð Bjarmason, May 28, 2021
  84. 01/13 send-email tests: support GIT_TEST_PERL_FATAL_WARNINGS=trueÆvar Arnfjörð Bjarmason, May 28, 2021
  85. 03/13 send-email: remove non-working support for "sendemail.smtpssl"Ævar Arnfjörð Bjarmason, May 28, 2021
  86. 02/13 send-email tests: test for boolean variables without a valueÆvar Arnfjörð Bjarmason, May 28, 2021
  87. Jeff KingJul 10, 2021
  88. 04/13 send-email: refactor sendemail.smtpencryption config parsingÆvar Arnfjörð Bjarmason, May 28, 2021
  89. 06/13 send-email: lazily load config for a big speedupÆvar Arnfjörð Bjarmason, May 28, 2021
  90. 05/13 send-email: copy "config_regxp" into git-send-email.perlÆvar Arnfjörð Bjarmason, May 28, 2021
  91. 07/13 send-email: lazily shell out to "git var"Ævar Arnfjörð Bjarmason, May 28, 2021
  92. 09/13 send-email: get rid of indirect object syntaxÆvar Arnfjörð Bjarmason, May 28, 2021
  93. 08/13 send-email: use function syntax instead of barewordsÆvar Arnfjörð Bjarmason, May 28, 2021
  94. Felipe ContrerasMay 28, 2021
  95. Ævar Arnfjörð BjarmasonMay 29, 2021
  96. Felipe ContrerasMay 29, 2021
  97. 10/13 send-email: lazily load modules for a big speedupÆvar Arnfjörð Bjarmason, May 28, 2021
  98. Felipe ContrerasMay 28, 2021
  99. Ævar Arnfjörð BjarmasonMay 29, 2021
  100. Felipe ContrerasMay 29, 2021
  101. 12/13 send-email: move trivial config handling to PerlÆvar Arnfjörð Bjarmason, May 28, 2021
  102. 11/13 perl: lazily load some common Git.pm setup codeÆvar Arnfjörð Bjarmason, May 28, 2021
  103. 13/13 perl: nano-optimize by replacing Cwd::cwd() with Cwd::getcwd()Ævar Arnfjörð Bjarmason, May 28, 2021
  104. Felipe ContrerasMay 28, 2021
  105. Jeff KingMay 31, 2021
  106. Ævar Arnfjörð BjarmasonMay 31, 2021
  107. Jeff KingMay 31, 2021
  108. Elijah NewrenMay 27, 2021

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.