[2/3] configure: speed up check_deps()

Message ID 20180917025301.10812-2-jamrial@gmail.com
State New
Headers show
Series
  • Untitled series #142
Related show

Commit Message

James Almer Sept. 17, 2018, 2:53 a.m.
From: Avi Halachm <avihpit@yahoo.com>

x4 - x25 faster.

check_deps() recursively enables/disables components, and its loop is
iterated nearly 6000 times. It's particularly slow in bash - currently
consuming more than 50% of configure runtime, and about 20% with other
shells.

This commit applies few local optimizations, most effective first:
- Use $1 $2 ... instead of pushvar/popvar, and same at enable_deep*
- Abort early in one notable case - empty deps, to avoid costly no-op.
- Smaller changes which do add up:
  - Handle ${cfg}_checking locally instead of via enable[d]/disable
  - ${cfg}_checking: test done before inprogress - x2 faster in 50%+
  - one eval instead of several at the empty-deps early abort path.

- The "actual work" part is unmodified - just its surroundings.

Biggest speedups (relative and absolute) are observed with bash.

Signed-off-by: James Almer <jamrial@gmail.com>
---
 configure | 83 ++++++++++++++++++++++++++++---------------------------
 1 file changed, 43 insertions(+), 40 deletions(-)

Patch

diff --git a/configure b/configure
index be348e881..a70136dc1 100755
--- a/configure
+++ b/configure
@@ -532,13 +532,10 @@  disable_sanitized(){
 do_enable_deep(){
     for var; do
         enabled $var && continue
-        eval sel="\$${var}_select"
-        eval sgs="\$${var}_suggest"
-        pushvar var sgs
-        enable_deep $sel
-        popvar sgs
-        enable_deep_weak $sgs
-        popvar var
+        set -- $var
+        eval enable_deep \$${var}_select
+        var=$1
+        eval enable_deep_weak \$${var}_suggest
     done
 }
 
@@ -550,9 +547,9 @@  enable_deep(){
 enable_deep_weak(){
     for var; do
         disabled $var && continue
-        pushvar var
+        set -- $var
         do_enable_deep $var
-        popvar var
+        var=$1
         enable_weak $var
     done
 }
@@ -609,38 +606,44 @@  is_in(){
 
 check_deps(){
     for cfg; do
-        enabled ${cfg}_checking && die "Circular dependency for $cfg."
-        disabled ${cfg}_checking && continue
-        enable ${cfg}_checking
-
-        eval dep_all="\$${cfg}_deps"
-        eval dep_any="\$${cfg}_deps_any"
-        eval dep_con="\$${cfg}_conflict"
-        eval dep_sel="\$${cfg}_select"
-        eval dep_sgs="\$${cfg}_suggest"
-        eval dep_ifa="\$${cfg}_if"
-        eval dep_ifn="\$${cfg}_if_any"
-
-        pushvar cfg dep_all dep_any dep_con dep_sel dep_sgs dep_ifa dep_ifn
-        check_deps $dep_all $dep_any $dep_con $dep_sel $dep_sgs $dep_ifa $dep_ifn
-        popvar cfg dep_all dep_any dep_con dep_sel dep_sgs dep_ifa dep_ifn
-
-        [ -n "$dep_ifa" ] && { enabled_all $dep_ifa && enable_weak $cfg; }
-        [ -n "$dep_ifn" ] && { enabled_any $dep_ifn && enable_weak $cfg; }
-        enabled_all  $dep_all || disable $cfg
-        enabled_any  $dep_any || disable $cfg
-        disabled_all $dep_con || disable $cfg
-        disabled_any $dep_sel && disable $cfg
-
-        enabled $cfg && enable_deep_weak $dep_sel $dep_sgs
-
-        for dep in $dep_all $dep_any $dep_sel $dep_sgs; do
-            # filter out library deps, these do not belong in extralibs
-            is_in $dep $LIBRARY_LIST && continue
-            enabled $dep && eval append ${cfg}_extralibs ${dep}_extralibs
-        done
+        eval [ x\$${cfg}_checking = xdone ] && continue
+        eval [ x\$${cfg}_checking = xinprogress ] && die "Circular dependency for $cfg."
+
+        eval "
+        dep_all=\$${cfg}_deps
+        dep_any=\$${cfg}_deps_any
+        dep_con=\$${cfg}_conflict
+        dep_sel=\$${cfg}_select
+        dep_sgs=\$${cfg}_suggest
+        dep_ifa=\$${cfg}_if
+        dep_ifn=\$${cfg}_if_any
+        "
+
+        # most of the time here $cfg has no deps - avoid costly no-op work
+        if [ "$dep_all$dep_any$dep_con$dep_sel$dep_sgs$dep_ifa$dep_ifn" ]; then
+            eval ${cfg}_checking=inprogress
+
+            set -- $cfg "$dep_all" "$dep_any" "$dep_con" "$dep_sel" "$dep_sgs" "$dep_ifa" "$dep_ifn"
+            check_deps $dep_all $dep_any $dep_con $dep_sel $dep_sgs $dep_ifa $dep_ifn
+            cfg=$1; dep_all=$2; dep_any=$3; dep_con=$4; dep_sel=$5 dep_sgs=$6; dep_ifa=$7; dep_ifn=$8
+
+            [ -n "$dep_ifa" ] && { enabled_all $dep_ifa && enable_weak $cfg; }
+            [ -n "$dep_ifn" ] && { enabled_any $dep_ifn && enable_weak $cfg; }
+            enabled_all  $dep_all || disable $cfg
+            enabled_any  $dep_any || disable $cfg
+            disabled_all $dep_con || disable $cfg
+            disabled_any $dep_sel && disable $cfg
+
+            enabled $cfg && enable_deep_weak $dep_sel $dep_sgs
+
+            for dep in $dep_all $dep_any $dep_sel $dep_sgs; do
+                # filter out library deps, these do not belong in extralibs
+                is_in $dep $LIBRARY_LIST && continue
+                enabled $dep && eval append ${cfg}_extralibs ${dep}_extralibs
+            done
+        fi
 
-        disable ${cfg}_checking
+        eval ${cfg}_checking=done
     done
 }