Reduce overhead of tests/wrapper.as

tests/wrapper.as is a wrapper script that enables the test suite to
run Autoconf’s command line tools (autoconf, autoheader, etc.) without
having installed them first.  It’s written in m4sh.  All of the
programs it wraps are written in Perl.  Therefore, we can make the
wrapper more efficient by rewriting it in Perl and having it invoke
the real program with the ‘do’ builtin.  This cuts out the cost of
starting up a shell and crunching through m4sh initialization (order
of 400 lines of code).  Using ‘do’ means we only have to start up Perl
once.

‘make check TESTSUITEFLAGS="-j24"’ speeds up a small but consistently
measurable amount on my workstation.  The wall-clock time difference
would be bigger at lower levels of parallelism.

before:
wall    1m16.716s
user    16m44.847s
sys     12m6.452s

                 wall     user    sys    user+sys
autom4te         451.16   261.75  35.75  297.5
autoheader       188.9    42.54   6.1    48.64
autoupdate       47.25    5.39    0.73   6.12
autoreconf       35.68    1.66    0.28   1.94
autoscan         0.88     0.31    0.04   0.35
ifnames          0.25     0.2     0.02   0.22
autoconf         0.18     0.13    0.01   0.14

after:
wall    1m14.624s
user    16m21.883s
sys     11m37.521s

                 wall     user    sys    user+sys
autom4te         415.49   256.41  27.83  284.24
autoheader       170.87   40.97   3.94   44.91
autoupdate       44.7     5.26    0.59   5.85
autoreconf       33.42    1.54    0.13   1.67
autoscan         0.76     0.27    0.03   0.3
ifnames          0.21     0.18    0      0.18
autoconf         0.14     0.11    0      0.11

(Total time per program collected using BSD process accounting.)
This commit is contained in:
Zack Weinberg 2023-12-07 14:06:26 -05:00
parent 39d96e6fff
commit 5c388be8a7
9 changed files with 104 additions and 61 deletions

View File

@ -193,7 +193,8 @@ print {*STDERR} $me,
"\n"
if $verbose;
exec {$autom4te_command[0]} @autom4te_command;
exec {$autom4te_command[0]} @autom4te_command
or fatal "$autom4te_command[0]: $!\n";
### Setup "GNU" style for perl-mode and cperl-mode.
## Local Variables:

View File

@ -314,6 +314,7 @@ $out->close;
}
update_file ("$tmp/config.hin", "$config_h_in", $force);
exit 0;
### Setup "GNU" style for perl-mode and cperl-mode.
## Local Variables:

View File

@ -138,6 +138,7 @@ foreach (sort keys %occurrence)
{
print "$_ ", join (' ', sort keys %{$occurrence{$_}}), "\n";
}
exit 0;
### Setup "GNU" style for perl-mode and cperl-mode.
## Local Variables:

View File

@ -186,7 +186,7 @@ sub update_file ($$;$)
msg 'note', "'$to' is unchanged";
unlink ($from)
or fatal "cannot remove $from: $!";
return
return;
}
if (-f "$to")

View File

@ -159,7 +159,7 @@ m4_define([AT_CHECK_SHELL_SYNTAX],
AT_CHECK(["$SHELL_N" -n $1], [], [], [ignore])])
m4_define([AT_CHECK_PERL_SYNTAX],
[AT_CHECK([autom4te_perllibdir=$abs_top_srcdir/lib $PERL -c "$abs_top_builddir"/bin/$1],
[AT_CHECK([autom4te_perllibdir=$abs_top_srcdir/lib $PERL -c "$abs_top_builddir/$1"],
0, [], [ignore])])
## ------------------ ##

View File

@ -23,7 +23,7 @@ EXTRA_DIST += \
tests/local.at \
tests/mktests.pl \
tests/atlocal.in \
tests/wrapper.as \
tests/wrapper.in \
tests/statesave.m4
# Running the uninstalled scripts. Build them upon 'all', for the manpages.
@ -60,13 +60,10 @@ wrappers = \
CLEANFILES += \
tests/package.m4 \
tests/wrapper.in \
$(wrappers)
tests/wrapper.in: $(srcdir)/tests/wrapper.as $(m4sh_m4f_dependencies)
$(MY_AUTOM4TE) --language=M4sh $(srcdir)/tests/wrapper.as -o $@
edit_wrapper = sed \
-e 's|@PERL[@]|$(PERL)|g' \
-e 's|@wrap_program[@]|$(@F)|g' \
-e 's|@abs_top_srcdir[@]|$(abs_top_srcdir)|g' \
-e 's|@abs_top_builddir[@]|$(abs_top_builddir)|g' \
@ -75,7 +72,7 @@ edit_wrapper = sed \
$(wrappers): tests/wrapper.in
rm -f $@ $@.tmp
input=tests/wrapper.in \
&& $(edit_wrapper) tests/wrapper.in >$@.tmp
&& $(edit_wrapper) $(srcdir)/tests/wrapper.in >$@.tmp
chmod +x $@.tmp
chmod a-w $@.tmp
mv -f $@.tmp $@

View File

@ -50,7 +50,6 @@ AT_CHECK([test "$SHELL_N" != none || exit 77])
# Specify the absolute name of the tool, as some shells don't honor PATH when
# running 'sh PROG'.
AT_CHECK_SHELL_SYNTAX(["$abs_top_builddir/tests/autoconf"])
AT_CHECK_SHELL_SYNTAX(["$abs_top_builddir/tests/testsuite"])
# These are not built, they are in the src tree.
@ -68,13 +67,21 @@ AT_CLEANUP
AT_SETUP([Syntax of the Perl scripts])
AT_CHECK_PERL_SYNTAX([autoconf])
AT_CHECK_PERL_SYNTAX([autoheader])
AT_CHECK_PERL_SYNTAX([autom4te])
AT_CHECK_PERL_SYNTAX([autoreconf])
AT_CHECK_PERL_SYNTAX([autoscan])
AT_CHECK_PERL_SYNTAX([autoupdate])
AT_CHECK_PERL_SYNTAX([ifnames])
AT_CHECK_PERL_SYNTAX([bin/autoconf])
AT_CHECK_PERL_SYNTAX([bin/autoheader])
AT_CHECK_PERL_SYNTAX([bin/autom4te])
AT_CHECK_PERL_SYNTAX([bin/autoreconf])
AT_CHECK_PERL_SYNTAX([bin/autoscan])
AT_CHECK_PERL_SYNTAX([bin/autoupdate])
AT_CHECK_PERL_SYNTAX([bin/ifnames])
AT_CHECK_PERL_SYNTAX([tests/autoconf])
AT_CHECK_PERL_SYNTAX([tests/autoheader])
AT_CHECK_PERL_SYNTAX([tests/autom4te])
AT_CHECK_PERL_SYNTAX([tests/autoreconf])
AT_CHECK_PERL_SYNTAX([tests/autoscan])
AT_CHECK_PERL_SYNTAX([tests/autoupdate])
AT_CHECK_PERL_SYNTAX([tests/ifnames])
AT_CLEANUP

View File

@ -1,44 +0,0 @@
AS_INIT[]dnl -*- shell-script -*-
# wrapper.as -- running '@wrap_program@' as if it were installed.
# @configure_input@
# Copyright (C) 2003-2004, 2007, 2009-2017, 2020-2023 Free Software
# Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
testdir='@abs_top_builddir@/tests'
PATH=$testdir$PATH_SEPARATOR$PATH
AUTOCONF=autoconf
AUTOHEADER=autoheader
AUTOM4TE=autom4te
AUTOM4TE_CFG='@abs_top_builddir@/lib/autom4te.cfg'
autom4te_buildauxdir='@abs_top_srcdir@/build-aux'
autom4te_perllibdir='@abs_top_srcdir@/lib'
trailer_m4='@abs_top_srcdir@/lib/autoconf/trailer.m4'
export AUTOCONF AUTOHEADER AUTOM4TE AUTOM4TE_CFG
export autom4te_buildauxdir autom4te_perllibdir trailer_m4
case '@wrap_program@' in
ifnames)
# Does not have lib files.
exec '@abs_top_builddir@/bin/@wrap_program@' ${1+"$@"}
;;
*)
# We might need files from the build tree (frozen files), in
# addition of src files.
exec '@abs_top_builddir@/bin/@wrap_program@' \
-B '@abs_top_builddir@'/lib \
-B '@abs_top_srcdir@'/lib ${1+"$@"}
esac
exit 1

80
tests/wrapper.in Executable file
View File

@ -0,0 +1,80 @@
#! @PERL@
# wrapper.in -- running '@wrap_program@' as if it were installed.
# @configure_input@
# Copyright (C) 2003-2004, 2007, 2009-2017, 2020-2023 Free Software
# Foundation, Inc.
eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
if 0;
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
use 5.006;
use strict;
use warnings FATAL => 'all';
my $src_libdir = '@abs_top_srcdir@/lib';
$ENV{'autom4te_perllibdir'} = $src_libdir;
$ENV{'autom4te_buildauxdir'} = '@abs_top_srcdir@/build-aux';
$ENV{'trailer_m4'} = '@abs_top_srcdir@/lib/autoconf/trailer.m4';
my $wrapped_program = '@wrap_program@';
my $abs_wrapped_program = '@abs_top_builddir@/bin/@wrap_program@';
my $build_testdir = '@abs_top_builddir@/tests';
my $build_libdir = '@abs_top_builddir@/lib';
$ENV{'AUTOM4TE_CFG'} = '@abs_top_builddir@/lib/autom4te.cfg';
$ENV{'AUTOCONF'} = 'autoconf';
$ENV{'AUTOHEADER'} = 'autoheader';
$ENV{'AUTOM4TE'} = 'autom4te';
# Prepend $build_testdir to the path if it isn't there already.
if (!defined $ENV{'PATH'} || $ENV{'PATH'} eq '')
{
$ENV{'PATH'} = $build_testdir;
}
elsif ($ENV{'PATH'} !~ /^\Q$build_testdir\E[\\\/]?(?:[:;]|$)/)
{
no warnings 'once';
require Config;
$ENV{'PATH'} = $build_testdir . $Config::Config{'path_sep'} . $ENV{'PATH'};
}
# All the wrapped programs *except* ifnames might need to load
# .m4 and .m4f files from both the build and source libdirs.
unshift (@ARGV, '-B', $build_libdir, '-B', $src_libdir)
if $wrapped_program ne 'ifnames';
my $status = do $abs_wrapped_program;
exit $status if defined $status;
die "couldn't parse ${wrapped_program}: $@\n" if $@;
die "error reading ${wrapped_program}: $!\n";
### Setup "GNU" style for perl-mode and cperl-mode.
## Local Variables:
## mode: perl
## perl-indent-level: 2
## perl-continued-statement-offset: 2
## perl-continued-brace-offset: 0
## perl-brace-offset: 0
## perl-brace-imaginary-offset: 0
## perl-label-offset: -2
## cperl-indent-level: 2
## cperl-brace-offset: 0
## cperl-continued-brace-offset: 0
## cperl-label-offset: -2
## cperl-extra-newline-before-brace: t
## cperl-merge-trailing-else: nil
## cperl-continued-statement-offset: 2
## End: