[git commit] hush: speed optimizations

Denys Vlasenko vda.linux at googlemail.com
Thu Sep 29 17:50:55 UTC 2016


commit: https://git.busybox.net/busybox/commit/?id=46e6498b2afccd093d03697313e0d0c2f6e4d38d
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

Make o_addchr() faster: do not call o_grow_by() each time.
Create i_getch_and_eat_bkslash_nl(), use it instead of peek+getch pair.

function                                             old     new   delta
o_addchr                                              42      54     +12
parse_dollar                                         761     771     +10
o_grow_by                                             48      37     -11
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/1 up/down: 24/-11)             Total: 11 bytes

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 shell/hush.c | 33 +++++++++++++++++++++++++++------
 1 file changed, 27 insertions(+), 6 deletions(-)

diff --git a/shell/hush.c b/shell/hush.c
index 177a794..65d7d87 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -2373,7 +2373,7 @@ static ALWAYS_INLINE void o_free_unsafe(o_string *o)
 static void o_grow_by(o_string *o, int len)
 {
 	if (o->length + len > o->maxlen) {
-		o->maxlen += (2*len > B_CHUNK ? 2*len : B_CHUNK);
+		o->maxlen += (2 * len) | (B_CHUNK-1);
 		o->data = xrealloc(o->data, 1 + o->maxlen);
 	}
 }
@@ -2381,10 +2381,16 @@ static void o_grow_by(o_string *o, int len)
 static void o_addchr(o_string *o, int ch)
 {
 	debug_printf("o_addchr: '%c' o->length=%d o=%p\n", ch, o->length, o);
+	if (o->length < o->maxlen) {
+		/* likely. avoid o_grow_by() call */
+ add:
+		o->data[o->length] = ch;
+		o->length++;
+		o->data[o->length] = '\0';
+		return;
+	}
 	o_grow_by(o, 1);
-	o->data[o->length] = ch;
-	o->length++;
-	o->data[o->length] = '\0';
+	goto add;
 }
 
 #if 0
@@ -3909,6 +3915,22 @@ static int parse_group(o_string *dest, struct parse_context *ctx,
 	/* command remains "open", available for possible redirects */
 }
 
+static int i_getch_and_eat_bkslash_nl(struct in_str *input)
+{
+	for (;;) {
+		int ch, ch2;
+
+		ch = i_getch(input);
+		if (ch != '\\')
+			return ch;
+		ch2 = i_peek(input);
+		if (ch2 != '\n')
+			return ch;
+		/* backslash+newline, skip it */
+		i_getch(input);
+	}
+}
+
 static int i_peek_and_eat_bkslash_nl(struct in_str *input)
 {
 	for (;;) {
@@ -4149,8 +4171,7 @@ static int parse_dollar(o_string *as_string,
 		ch = i_getch(input); /* eat '{' */
 		nommu_addchr(as_string, ch);
 
-		i_peek_and_eat_bkslash_nl(input);
-		ch = i_getch(input); /* first char after '{' */
+		ch = i_getch_and_eat_bkslash_nl(input); /* first char after '{' */
 		/* It should be ${?}, or ${#var},
 		 * or even ${?+subst} - operator acting on a special variable,
 		 * or the beginning of variable name.


More information about the busybox-cvs mailing list