autoconf-patches
[Top][All Lists]
Advanced

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

faster m4_foreach


From: Eric Blake
Subject: faster m4_foreach
Date: Mon, 28 Jul 2008 17:54:46 +0000 (UTC)
User-agent: Loom/3.14 (http://gmane.org/)

While working with m4_set, I noticed a speed difference between:

m4_if([$#], [1], [], [$2[]$0([$1]_m4_shift2($@))])

and

m4_if([$#], [2], [], [$3[]$0([$1], m4_shift2($@))])

By injecting an ignored $2, we can avoid the m4_if embedded inside _m4_shift2, 
and instead use the faster m4_shift2 in $@ recursion (m4_joinall was already 
doing this, and I also used it in m4_set_add_all).  I noticed as much as 5% 
improvement on m4_foreach in isolation, although the improvement in real-life 
testcases is rather minor (and there is no improvement to m4 1.4.x, which isn't 
using $@ recursion in the first place).

With this patch, _m4_shift2, _m4_shift3, and _m4_cdr are now all unused within 
autoconf.  But even though they are undocumented, I won't delete them in case 
other code is using them in spite of their undocumented nature.

From: Eric Blake <address@hidden>
Date: Mon, 28 Jul 2008 11:24:03 -0600
Subject: [PATCH] Avoid _m4_shiftn for m4 1.6 speedup.

* lib/m4sugar/m4sugar.m4 (m4_foreach, _m4_foreach, m4_map)
(_m4_map, m4_map_sep): Rewrite recursion to use one less m4_if.
* lib/m4sugar/foreach.m4 (_m4_map): Accomodate changed signature.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog              |    5 +++++
 lib/m4sugar/foreach.m4 |    4 ++--
 lib/m4sugar/m4sugar.m4 |   22 ++++++++++++----------
 3 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 945891b..d46fd13 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2008-07-28  Eric Blake  <address@hidden>
 
+       Avoid _m4_shiftn for m4 1.6 speedup.
+       * lib/m4sugar/m4sugar.m4 (m4_foreach, _m4_foreach, m4_map)
+       (_m4_map, m4_map_sep): Rewrite recursion to use one less m4_if.
+       * lib/m4sugar/foreach.m4 (_m4_map): Accomodate changed signature.
+
        Implement O(n) unique element set creation.
        * lib/m4sugar/m4sugar.m4 (m4_set_add, m4_set_add_all)
        (m4_set_contains, m4_set_contents, m4_set_delete)
diff --git a/lib/m4sugar/foreach.m4 b/lib/m4sugar/foreach.m4
index d6a9f72..0b1d05c 100644
--- a/lib/m4sugar/foreach.m4
+++ b/lib/m4sugar/foreach.m4
@@ -162,8 +162,8 @@ m4_define([m4_dquote_elt],
 # m4_map/m4_map_sep only execute once; the speedup comes in fixing
 # _m4_map.  m4_foreach to the rescue.
 m4_define([_m4_map],
-[m4_if([$#], [1], [],
-       [m4_foreach([_m4_elt], [m4_shift($@)],
+[m4_if([$#], [2], [],
+       [m4_foreach([_m4_elt], [m4_shift2($@)],
                   [m4_apply([$1], m4_defn([_m4_elt]))])])])
 
 # m4_join(SEP, ARG1, ARG2...)
diff --git a/lib/m4sugar/m4sugar.m4 b/lib/m4sugar/m4sugar.m4
index 9da7d57..293e38e 100644
--- a/lib/m4sugar/m4sugar.m4
+++ b/lib/m4sugar/m4sugar.m4
@@ -958,14 +958,15 @@ m4_if(m4_defn([$1]), [$2], [],
 # as little as possible in _m4_foreach; each extra use requires that much
 # more memory for expansion.  So, rather than directly compare $2 against
 # [] and use m4_car/m4_cdr for recursion, we instead unbox the list (which
-# requires swapping the argument order in the helper) and use _m4_shift3
-# to detect when recursion is complete.
+# requires swapping the argument order in the helper), insert an ignored
+# third argument, and use m4_shift3 to detect when recursion is complete.
 m4_define([m4_foreach],
-[m4_pushdef([$1])_$0([$1], [$3]m4_if([$2], [], [], [, $2]))m4_popdef([$1])])
+[m4_if([$2], [], [],
+       [m4_pushdef([$1])_$0([$1], [$3], [], $2)m4_popdef([$1])])])
 
 m4_define([_m4_foreach],
-[m4_if([$#], [2], [],
-       [m4_define([$1], [$3])$2[]$0([$1], [$2]_m4_shift3($@))])])
+[m4_if([$#], [3], [],
+       [m4_define([$1], [$4])$2[]$0([$1], [$2], m4_shift3($@))])])
 
 
 # m4_foreach_w(VARIABLE, LIST, EXPRESSION)
@@ -990,13 +991,14 @@ m4_define([m4_foreach_w],
 #
 # Since LIST may be quite large, we want to minimize how often it appears
 # in the expansion.  Rather than use m4_car/m4_cdr iteration, we unbox the
-# list, and use _m4_shift2 to detect the end of recursion.
+# list, ignore the second argument, and use m4_shift2 to detect the end of
+# recursion.
 m4_define([m4_map],
 [m4_if([$2], [], [],
-       [_$0([$1], $2)])])
+       [_$0([$1], [], $2)])])
 m4_define([_m4_map],
-[m4_if([$#], [1], [],
-       [m4_apply([$1], [$2])$0([$1]_m4_shift2($@))])])
+[m4_if([$#], [2], [],
+       [m4_apply([$1], [$3])$0([$1], m4_shift2($@))])])
 
 
 # m4_map_sep(MACRO, SEPARATOR, LIST)
@@ -1006,7 +1008,7 @@ m4_define([_m4_map],
 # SEPARATOR is not further expanded.
 m4_define([m4_map_sep],
 [m4_if([$3], [], [],
-       [m4_apply([$1], m4_car($3))_m4_map([[$2]$1]_m4_shift2(,$3))])])
+       [m4_apply([$1], m4_car($3))_m4_map([[$2]$1], $3)])])
 
 
 ## --------------------------- ##
-- 
1.5.6.4







reply via email to

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