diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2018-03-25 11:50:36 +0800 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2018-04-02 23:30:44 +0800 |
commit | 42b730b034eebd0e9da4aa014785a3ee5de436be (patch) | |
tree | b56cfddd88e9eccf1fe5b5a6dcd4f255e5ea7c29 | |
parent | expand: Fix ghost fields with unquoted $@/$* (diff) | |
download | dash-42b730b034eebd0e9da4aa014785a3ee5de436be.tar.gz dash-42b730b034eebd0e9da4aa014785a3ee5de436be.zip |
builtin: Fix echo performance regression
The commit d6c0e1e2ffbf7913ab69d51cc794d48d41c8fcb1 ("[BUILTIN] Handle embedded NULs correctly in printf") caused a performance regression in the echo built-in because every echo call now goes through the printf %b slow path where the string is always printed twice to ensure the space padding is correct in the presence of NUL characters. In fact this regression applies to printf %b as well. This is easily fixed by making printf %b take the fast path when no precision/field width modifiers are present. This patch also changes the second strchurnul call to strspn which generates slightly better code. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r-- | src/bltin/printf.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/src/bltin/printf.c b/src/bltin/printf.c index ec7c8c2..eaf14b6 100644 --- a/src/bltin/printf.c +++ b/src/bltin/printf.c @@ -98,20 +98,25 @@ static int print_escape_str(const char *f, int *param, int *array, char *s) int total; setstackmark(&smark); - done = conv_escape_str(s, &p); - q = stackblock(); - len = p - q; + done = conv_escape_str(s, &q); + p = stackblock(); + len = q - p; + total = len - 1; + + if (f[1] == 's') + goto easy; - p = makestrspace(len, p); - memset(p, 'X', len - 1); - p[len - 1] = 0; + p = makestrspace(len, q); + memset(p, 'X', total); + p[total] = 0; q = stackblock(); total = ASPF(&p, f, p); len = strchrnul(p, 'X') - p; - memcpy(p + len, q, strchrnul(p + len, ' ') - (p + len)); + memcpy(p + len, q, strspn(p + len, "X")); +easy: out1mem(p, total); popstackmark(&smark); |