libtool-patches
[Top][All Lists]
Advanced

[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
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]