Subject: bug#13472: [PATCH] libtool: speed up by pre-cutting sed's input by dd

From: Pavel Raiskup <[email-masked]>
Date: Thu, 25 Apr 2013 13:48:35 +0200

The execute mode was too slow when any parameter of executed
command was a big binary file not having any newlines inside:

    $ libtool --mode=execute ls BIG_FILE_WITHOUT_NEWLINES

This was because of the lalib detection among parameters.  Every
such file is pre-filtered by sed uitlity.  That big slowdown
is there because the sed utility tries to read and cache
_unlimitedly_ the first four lines of these files.

The new approach is pre-cutting relevant files by dd utility at
4kB size.

* build-aux/ltmain.in (func_try_sizelim): New function.
(func_lalib_p): Cut the input file at 4kB before it is passed to
sed utility.
* gl/build-aux/funclib.sh: New variable $DD.
* m4/libtool.m4 (_LT_PROG_DD): New macro.
(_LT_SETUP): Require _LT_PROG_DD for the dd detection.
---
 build-aux/ltmain.in     | 14 +++++++++++++-
 gl/build-aux/funclib.sh |  1 +
 m4/libtool.m4           | 14 ++++++++++++++
 3 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/build-aux/ltmain.in b/build-aux/ltmain.in
index 4c56b98..4a21b58 100644
--- a/build-aux/ltmain.in
+++ b/build-aux/ltmain.in
@@ -568,6 +568,18 @@ $1
 _LTECHO_EOF'
 }
 
+# func_try_sizelim file n
+# try to write at most the first N bytes from FILE to the standard output when
+# possible, otherwise put whole file
+func_try_sizelim ()
+{
+  if [ -n "$DD" ]; then
+    $DD if="$1" bs=$2 count=1 2>/dev/null
+  else
+    cat "$1"
+  fi
+}
+
 # func_lalib_p file
 # True iff FILE is a libtool '.la' library or '.lo' object file.
 # This function is only a basic sanity check; it will hardly flush out
@@ -575,7 +587,7 @@ _LTECHO_EOF'
 func_lalib_p ()
 {
     test -f "$1" &&
-      $SED -e 4q "$1" 2>/dev/null \
+        func_try_sizelim "$1" 4096 | $SED -e 4q 2>/dev/null \
         | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
 }
 
diff --git a/gl/build-aux/funclib.sh b/gl/build-aux/funclib.sh
index 8a212d1..ff9680d 100644
--- a/gl/build-aux/funclib.sh
+++ b/gl/build-aux/funclib.sh
@@ -135,6 +135,7 @@ fi
 # in the command search PATH.
 
 : ${CP="cp -f"}
+: ${DD="$LTDD"}
 : ${ECHO="$bs_echo"}
 : ${EGREP="grep -E"}
 : ${FGREP="grep -F"}
diff --git a/m4/libtool.m4 b/m4/libtool.m4
index 3f50b0c..7fa3d9b 100644
--- a/m4/libtool.m4
+++ b/m4/libtool.m4
@@ -175,6 +175,7 @@ m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
 m4_require([_LT_CMD_OLD_ARCHIVE])dnl
 m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
 m4_require([_LT_WITH_SYSROOT])dnl
+m4_require([_LT_PROG_DD])dnl
 
 _LT_CONFIG_LIBTOOL_INIT([
 # See if we are running on zsh, and set the options which allow our
@@ -898,6 +899,19 @@ dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
 dnl AC_DEFUN([AC_LIBTOOL_RC], [])

+# _LT_PROG_DD
+# -----------
+# Try to find dd program and set the $LTDD variable to point to it, otherwise
+# set the $LTDD variable to be empty.
+m4_defun([_LT_PROG_DD],[
+m4_require([_LT_DECL_DLLTOOL])
+LTDD=dd
+$LTDD if=/dev/zero of=/dev/null bs=1 count=16K >/dev/null 2>/dev/null
+test $? -ne 0 && LTDD=
+_LT_DECL([], [LTDD], [1], [The dd program])dnl
+]) # _LT_PROG_DD
+
+
 # _LT_TAG_COMPILER
 # ----------------
 m4_defun([_LT_TAG_COMPILER],
-- 
1.8.1.4