[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
func_arith and func_len
From: |
Ralf Wildenhues |
Subject: |
func_arith and func_len |
Date: |
Sat, 19 Apr 2008 12:20:08 +0200 |
User-agent: |
Mutt/1.5.17+20080114 (2008-01-14) |
Let's reuse at_func_arith from Autotest, to redo one of the link mode
speedups that fell under the cracks a couple of years ago.
IIRC somebody else suggested this recently, but I don't remember who.
Please speak up so I can put your name in the ChangeLog entry.
There are two expr calls that really matter for the case where we exceed
the command line length: those run per-object in the piecewise archive
linking and the reloadable object loops. Not only the high number of
forks, also they amount they counted grew quadratically in the number of
objects.
Note that for pre-Posix shells, the number of forks doubles in those
loops (but the quadratic counting is not present there either); for
practical cases that will lead to a slow-down with those shells.
OK to apply?
Example timings for an extreme example: CLN (850some objects),
max_cmd_len manually reduces to 2000, GNU ld linkscript turned off (so
that both piecewise archive linking and reloadable objects are used),
GNU/Linux system:
before patch:
3.23user 2.18system 0:05.51elapsed 98%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+78176outputs (0major+938094minor)pagefaults 0swaps
after patch:
1.90user 0.54system 0:02.53elapsed 96%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+78152outputs (0major+59756minor)pagefaults 0swaps
Of course, most practical cases will not look this extreme. But on w32,
there should be a noticeable speedup.
I have checked using this example that the command lines generated are
equal, give or take one object, due to the slightly different length
computations (a couple of characters added here or there).
Thanks,
Ralf
2008-04-19 Ralf Wildenhues <address@hidden>
Exploit shell arithmetic expansion and ${#var}.
* libltdl/m4/libtool.m4 (_LT_CHECK_SHELL_FEATURES): Also check
for arithmetic expansion, and ${#var}.
(_LT_PROG_XSI_SHELLFNS): Define func_arith and func_len
accordingly, falling back on 'expr'. Note that the argument to
func_len may not start with a hyphen. In the pre-Posix
fallback, take care not to rely on the exit status of the
variable assignment (not portable), but set the length to
$max_cmd_len instead.
* libltdl/config/ltmain.m4sh (func_mode_link): Use func_arith
and func_len throughout for integer arithmetic, fixing
quadratical amount of counting for reloadable object and
piecewise archive linking. Change all comparisons with
max_cmd_len to test for smaller, non-equal length.
diff --git a/libltdl/config/ltmain.m4sh b/libltdl/config/ltmain.m4sh
index 5018de8..378acae 100644
--- a/libltdl/config/ltmain.m4sh
+++ b/libltdl/config/ltmain.m4sh
@@ -2187,7 +2187,8 @@ func_extract_archives ()
while :; do
case " $extracted_archives " in
*" $my_xlib_u "*)
- extracted_serial=`expr $extracted_serial + 1`
+ func_arith $extracted_serial + 1
+ extracted_serial=$func_arith_result
my_xlib_u=lt$extracted_serial-$my_xlib ;;
*) break ;;
esac
@@ -4656,7 +4657,8 @@ func_mode_link ()
# bleh windows
case $host in
*cygwin* | mingw*)
- major=`expr $current - $age`
+ func_arith $current - $age
+ major=$func_arith_result
versuffix="-$major"
;;
esac
@@ -5219,7 +5221,8 @@ func_mode_link ()
#
case $version_type in
darwin|linux|osf|windows|none)
- current=`expr $number_major + $number_minor`
+ func_arith $number_major + $number_minor
+ current=$func_arith_result
age="$number_minor"
revision="$number_revision"
;;
@@ -5229,7 +5232,8 @@ func_mode_link ()
age="0"
;;
irix|nonstopux)
- current=`expr $number_major + $number_minor`
+ func_arith $number_major + $number_minor
+ current=$func_arith_result
age="$number_minor"
revision="$number_minor"
lt_irix_increment=no
@@ -5283,10 +5287,12 @@ func_mode_link ()
darwin)
# Like Linux, but with the current version available in
# verstring for coding it into the library header
- major=.`expr $current - $age`
+ func_arith $current - $age
+ major=.$func_arith_result
versuffix="$major.$age.$revision"
# Darwin ld doesn't like 0 for these options...
- minor_current=`expr $current + 1`
+ func_arith $current + 1
+ minor_current=$func_arith_result
xlcverstring="${wl}-compatibility_version ${wl}$minor_current
${wl}-current_version ${wl}$minor_current.$revision"
verstring="-compatibility_version $minor_current -current_version
$minor_current.$revision"
;;
@@ -5303,10 +5309,11 @@ func_mode_link ()
irix | nonstopux)
if test "X$lt_irix_increment" = "Xno"; then
- major=`expr $current - $age`
+ func_arith $current - $age
else
- major=`expr $current - $age + 1`
+ func_arith $current - $age + 1
fi
+ major=$func_arith_result
case $version_type in
nonstopux) verstring_prefix=nonstopux ;;
@@ -5317,8 +5324,10 @@ func_mode_link ()
# Add in all the interfaces that we are compatible with.
loop=$revision
while test "$loop" -ne 0; do
- iface=`expr $revision - $loop`
- loop=`expr $loop - 1`
+ func_arith $revision - $loop
+ iface=$func_arith_result
+ func_arith $loop - 1
+ loop=$func_arith_result
verstring="$verstring_prefix$major.$iface:$verstring"
done
@@ -5328,20 +5337,24 @@ func_mode_link ()
;;
linux)
- major=.`expr $current - $age`
+ func_arith $current - $age
+ major=.$func_arith_result
versuffix="$major.$age.$revision"
;;
osf)
- major=.`expr $current - $age`
+ func_arith $current - $age
+ major=.$func_arith_result
versuffix=".$current.$age.$revision"
verstring="$current.$age.$revision"
# Add in all the interfaces that we are compatible with.
loop=$age
while test "$loop" -ne 0; do
- iface=`expr $current - $loop`
- loop=`expr $loop - 1`
+ func_arith $current - $loop
+ iface=$func_arith_result
+ func_arith $loop - 1
+ loop=$func_arith_result
verstring="$verstring:${iface}.0"
done
@@ -5362,7 +5375,8 @@ func_mode_link ()
windows)
# Use '-' rather than '.', since we only want one
# extension on DOS 8.3 filesystems.
- major=`expr $current - $age`
+ func_arith $current - $age
+ major=$func_arith_result
versuffix="-$major"
;;
@@ -6022,8 +6036,9 @@ EOF
for cmd in $cmds; do
IFS="$save_ifs"
eval cmd=\"$cmd\"
- if len=`expr "X$cmd" : ".*"` &&
- test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1;
then
+ func_len " $cmd"
+ len=$func_len_result
+ if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1;
then
func_show_eval "$cmd" 'exit $?'
skipped_export=false
else
@@ -6126,8 +6141,9 @@ EOF
fi
if test "X$skipped_export" != "X:" &&
- len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
- test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ func_len " $test_cmds" &&
+ len=$func_len_result &&
+ test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
:
else
# The command line is too long to link in one step, link piecewise
@@ -6187,14 +6203,20 @@ EOF
if test -n "$save_libobjs"; then
func_verbose "creating reloadable object files..."
output=$output_objdir/$output_la-${k}.$objext
+ eval test_cmds=\"$reload_cmds\"
+ func_len " $test_cmds"
+ len0=$func_len_result
+ len=$len0
+
# Loop over the list of objects to be linked.
for obj in $save_libobjs
do
- eval test_cmds=\"$reload_cmds $objlist $last_robj\"
+ func_len " $obj"
+ func_arith $len + $func_len_result
+ len=$func_arith_result
if test "X$objlist" = X ||
- { len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
- test "$len" -le "$max_cmd_len"; }; then
- objlist="$objlist $obj"
+ test "$len" -lt "$max_cmd_len"; then
+ func_append objlist " $obj"
else
# The command $test_cmds is almost too long, add a
# command to the queue.
@@ -6207,10 +6229,13 @@ EOF
eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist
$last_robj~\$RM $last_robj\"
fi
last_robj=$output_objdir/$output_la-${k}.$objext
- k=`expr $k + 1`
+ func_arith $k + 1
+ k=$func_arith_result
output=$output_objdir/$output_la-${k}.$objext
objlist=$obj
- len=1
+ func_len " $last_robj"
+ func_arith $len0 + $func_len_result
+ len=$func_arith_result
fi
done
# Handle the remaining objects by creating one last
@@ -6945,7 +6970,8 @@ EOF
# Make sure we don't pick an alternate name that also
# overlaps.
newobj=lt$counter-$objbase
- counter=`expr $counter + 1`
+ func_arith $counter + 1
+ counter=$func_arith_result
case " $oldobjs " in
*[\ /]"$newobj "*) ;;
*) if test ! -f "$gentop/$newobj"; then break; fi ;;
@@ -6960,8 +6986,9 @@ EOF
fi
eval cmds=\"$old_archive_cmds\"
- if len=`expr "X$cmds" : ".*" 2>/dev/null` &&
- test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ func_len " $cmds"
+ len=$func_len_result
+ if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
cmds=$old_archive_cmds
else
# the command line is too long to link in one step, link in parts
@@ -6971,18 +6998,23 @@ EOF
objlist=
concat_cmds=
save_oldobjs=$oldobjs
+ oldobjs=
# Is there a better way of finding the last object in the list?
for obj in $save_oldobjs
do
last_oldobj=$obj
done
+ eval test_cmds=\"$old_archive_cmds\"
+ func_len " $test_cmds"
+ len0=$func_len_result
+ len=$len0
for obj in $save_oldobjs
do
- oldobjs="$objlist $obj"
- objlist="$objlist $obj"
- eval test_cmds=\"$old_archive_cmds\"
- if len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
- test "$len" -le "$max_cmd_len"; then
+ func_len " $obj"
+ func_arith $len + $func_len_result
+ len=$func_arith_result
+ func_append objlist " $obj"
+ if test "$len" -lt "$max_cmd_len"; then
:
else
# the above command should be used before it gets too long
@@ -6993,6 +7025,7 @@ EOF
test -z "$concat_cmds" || concat_cmds=$concat_cmds~
eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
objlist=
+ len=$len0
fi
done
RANLIB=$save_RANLIB
diff --git a/libltdl/m4/libtool.m4 b/libltdl/m4/libtool.m4
index 1fc9ccf..cdab378 100644
--- a/libltdl/m4/libtool.m4
+++ b/libltdl/m4/libtool.m4
@@ -7054,7 +7054,9 @@ m4_defun([_LT_CHECK_SHELL_FEATURES],
xsi_shell=no
( _lt_dummy="a/b/c"
test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
- = c,a/b,, ) >/dev/null 2>&1 \
+ = c,a/b,, \
+ && eval 'test $(( 1 + 1 )) -eq 2 \
+ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
&& xsi_shell=yes
AC_MSG_RESULT([$xsi_shell])
_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell'])
@@ -7173,6 +7175,19 @@ func_xform ()
func_xform_result=${1%.*}.lo
}
+# func_arith arithmetic-term...
+func_arith ()
+{
+ func_arith_result=$(( $[*] ))
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+ func_len_result=${#1}
+}
+
_LT_EOF
;;
*) # Bourne compatible functions.
@@ -7240,6 +7255,20 @@ func_xform ()
{
func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[[^.]]*$/.lo/'`
}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+ func_arith_result=`expr "address@hidden"`
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+ func_len_result=`expr "$[1]" : ".*" 2>/dev/null || echo $max_cmd_len`
+}
+
_LT_EOF
esac
- func_arith and func_len,
Ralf Wildenhues <=