libtool
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Performance issue of libtool-2.4.4


From: Richard Purdie
Subject: Re: Performance issue of libtool-2.4.4
Date: Mon, 09 Feb 2015 23:36:28 +0000

On Mon, 2015-02-09 at 13:05 +0000, Richard Purdie wrote:
> In an effort to get to the bottom of this I made a git bisection, timing
> the performance of building xz with make -j1 using each different
> libtool.
> 
> The issues come down to this commit:
> 
> http://git.savannah.gnu.org/cgit/libtool.git/commit/?id=0a42997c6032b9550a009a271552e811bfbcc430
> 
> libtool: rewritten over funclib.sh instead of general.m4sh.
> 
> Before that, I get a time of about 20s, after it, 39s. If I cherry-pick
> in the fix in master mentioned above, I get 27s.
> 
> So whilst things are better (thanks!), the above change is still causing
> a regression in the performance somewhere else. Any ideas what else in
> that rather large change may be causing this?

To further narrow this down, of the changes in the above commit, the
problem appears to be in the changes to the option parsing code. I've
included the diff below which if I apply on top of the above, I get the
speed back. I've left the func_split_short_opt/func_split_long_opt code
in there but that is worth a tiny part of the speed, the issues are
around the addition of the func_options call.

As yet I don't know enough about the code in question to know why this
is an issue but traces of libtool show a lot more looping in code to do
with argument parsing and quoting.

Cheers,

Richard



--- libtool-bad 2015-02-09 16:34:30.702068736 +0000
+++ libtool     2015-02-09 23:31:37.238750764 +0000
@@ -791,13 +791,77 @@
     fi
 }
 
+exit_status=$EXIT_SUCCESS
 
-# libtool_options_prep [ARG]...
-# -----------------------------
-# Preparation for options parsed by libtool.
-libtool_options_prep ()
-{
-    $debug_mode
+# We should try to minimise forks, especially on Windows where they are
+# unreasonably slow, so skip the feature probes when bash or zsh are
+# being used:
+if test set = "${BASH_VERSION+set}$ZSH_VERSION"; then
+    : ${lt_HAVE_ARITH_OP="yes"}
+    : ${lt_HAVE_XSI_OPS="yes"}
+fi
+
+
+
+# lt_HAVE_XSI_OPS
+# Can be empty, in which case the shell is probed, "yes" if XSI length
+# and matching operators are useable or anything else if they do not work.
+test -z "$lt_HAVE_XSI_OPS" \
+    && (eval 'x=a/b/c;
+      test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \
+    && lt_HAVE_XSI_OPS=yes
+
+
+
+# If this shell supports prefix and suffix pattern removal, then
+# use them to avoid forking. Hide the definition in an eval in case
+# the shell chokes on unsupported syntax...
+if test yes = "$lt_HAVE_XSI_OPS"; then
+  # func_split_short_opt shortopt
+  # Set func_split_short_opt_name and func_split_short_opt_arg shell
+  # variables after splitting SHORTOPT after the 2nd character.
+  eval 'func_split_short_opt ()
+  {
+    $debug_cmd
+
+    func_split_short_opt_arg=${1#??}
+    func_split_short_opt_name=${1%"$func_split_short_opt_arg"}
+  }'
+
+  # func_split_long_opt longopt
+  # Set func_split_long_opt_name and func_split_long_opt_arg shell
+  # variables after splitting LONGOPT at the `=' sign.
+  eval 'func_split_long_opt ()
+  {
+    func_split_long_opt_name=${1%%=*}
+    func_split_long_opt_arg=${1#*=}
+  }'
+else
+  # ...otherwise fall back to using sed.
+  func_split_short_opt ()
+  {
+    my_sed_short_opt='1s/^\(..\).*$/\1/;q'
+    my_sed_short_rest='1s/^..\(.*\)$/\1/;q'
+
+    func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"`
+    func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"`
+  }
+
+  func_split_long_opt ()
+  {
+    my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q'
+    my_sed_long_arg='1s/^--[^=]*=//'
+
+    func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"`
+    func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"`
+  }
+fi
+
+debug_cmd=${debug_cmd-':'}
+opt_warning=:
+opt_verbose=:
+opt_verbose=false
+exit_cmd=:
 
     # Option defaults:
     opt_config=false
@@ -836,26 +900,23 @@
       ;;
     esac
 
-    # Pass back the list of options.
-    func_quote_for_eval ${1+"$@"}
-    libtool_options_prep_result=$func_quote_for_eval_result
-}
-func_add_hook func_options_prep libtool_options_prep
 
 
-# libtool_parse_options [ARG]...
-# ---------------------------------
-# Provide handling for libtool specific options.
-libtool_parse_options ()
+# Parse options once, thoroughly.  This comes as soon as possible in the
+# script to make things like `--version' happen as quickly as we can.
 {
-    $debug_cmd
-
     # Perform our own loop to consume as many options as possible in
     # each iteration.
     while test $# -gt 0; do
       _G_opt=$1
       shift
       case $_G_opt in
+
+        --debug|-x)    debug_cmd='set -x'
+                       func_echo "enabling shell trace mode"
+                       $debug_cmd
+                       ;;
+
         --dry-run|--dryrun|-n)
                         opt_dry_run=:
                         ;;
@@ -927,29 +988,39 @@
                         func_append preserve_args " $_G_opt"
                         ;;
 
-       # An option not handled by this hook function:
-        *)             set dummy "$_G_opt" ${1+"$@"};  shift; break  ;;
-      esac
-    done
-
-
-    # save modified positional parameters for caller
-    func_quote_for_eval ${1+"$@"}
-    libtool_parse_options_result=$func_quote_for_eval_result
-}
-func_add_hook func_parse_options libtool_parse_options
 
 
+      -\?|-h)          func_usage                              ;;
+      --help)          func_help                               ;;
+      --version)       func_version                            ;;
+
+      # Separate optargs to long options:
+      --*=*)
+                       func_split_long_opt "$_G_opt"
+                       set dummy "$func_split_long_opt_name" 
"$func_split_long_opt_arg" ${1+"$@"}
+                       shift
+                       ;;
+
+      # Separate non-argument short options:
+      -\?*|-h*|-n*|-v*)
+                       func_split_short_opt "$_G_opt"
+                       set dummy "$func_split_short_opt_name" 
"-$func_split_short_opt_arg" ${1+"$@"}
+                       shift
+                       ;;
+
+      --)              break                                   ;;
+      -*)              func_fatal_help "unrecognized option \`$_G_opt'" ;;
+
+          *)           set dummy "$_G_opt" ${1+"$@"};  shift; break  ;;
+        esac
+      done
 
-# libtool_validate_options [ARG]...
-# ---------------------------------
 # Perform any sanity checks on option settings and/or unconsumed
 # arguments.
-libtool_validate_options ()
-{
+
     # save first non-option argument
-    if test 0 -lt $#; then
-      nonopt=$1
+    if test "$#" -gt 0; then
+      nonopt=$_G_opt
       shift
     fi
 
@@ -989,17 +1060,11 @@
       help="Try \`$progname --help --mode=$opt_mode' for more information."
     }
 
-    # Pass back the unparsed argument list
-    func_quote_for_eval ${1+"$@"}
-    libtool_validate_options_result=$func_quote_for_eval_result
-}
-func_add_hook func_validate_options libtool_validate_options
 
+  # Bail if the options were screwed
+  $exit_cmd $EXIT_FAILURE
+}
 
-# Process options as early as possible so that --help and --version
-# can return quickly.
-func_options ${1+"$@"}
-eval set dummy "$func_options_result"; shift
 
 
 




reply via email to

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