From 769b8a1c42a1c44fec930795fd3ce8799ec39537 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sat, 12 Dec 2020 05:53:16 -0600 Subject: Speed up seq: use toybuf for block writes and add an integer fast path. --- toys/lsb/seq.c | 88 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 25 deletions(-) (limited to 'toys/lsb') diff --git a/toys/lsb/seq.c b/toys/lsb/seq.c index 988466b7..45c82d51 100644 --- a/toys/lsb/seq.c +++ b/toys/lsb/seq.c @@ -28,7 +28,7 @@ config SEQ GLOBALS( char *s, *f; - int precision; + int precision, buflen; ) // Ensure there's one %f escape with correct attributes @@ -37,10 +37,8 @@ static void insanitize(char *f) char *s = next_printf(f, 0); if (!s) error_exit("bad -f no %%f"); - if (-1 == stridx("aAeEfFgG", *s) || (s = next_printf(s, 0))) { - // The @ is a byte offset, not utf8 chars. Waiting for somebody to complain. + if (-1 == stridx("aAeEfFgG", *s) || (s = next_printf(s, 0))) error_exit("bad -f '%s'@%d", f, (int)(s-f+1)); - } } // Parse a numeric argument setting *prec to the precision of this argument. @@ -54,11 +52,38 @@ static double parsef(char *s) return xstrtod(s); } +// fast integer conversion to decimal string +char *itoa(char *s, int i) +{ + char buf[16], *ff = buf; + + if (i<0) { + *s++ = '-'; + i = -i; + } + do *ff++ = '0'+i%10; while ((i /= 10)); + do *s++ = *--ff; while (ff>buf); + *s++ = '\n'; + + return s; +} + +char *flush_toybuf(char *ss) +{ + if (ss-toybuf0) for (; ii<=len; ii += inc) + ss = flush_toybuf(itoa(ss, ii)); + else if (inc<0) for (; ii>=len; ii += inc) + ss = flush_toybuf(itoa(ss, ii)); + if (ss != toybuf) write(1, toybuf, ss-toybuf); + + return; } // Other implementations output nothing if increment is 0 and first > last, @@ -86,14 +124,14 @@ void seq_main(void) // nothing for all three, if you want endless output use "yes". if (!increment) return; - i = 0; - for (;;) { + // Slow path, floating point and fancy sprintf() patterns + for (ii = 0, ss = toybuf;; ii++) { // Multiply to avoid accumulating rounding errors from increment. - dd = first+i*increment; + dd = first+ii*increment; if ((increment<0 && dd0 && dd>last)) break; - if (i++) printf("%s", TT.s); - printf(TT.f, dd); + if (ii) ss = flush_toybuf(stpcpy(ss, TT.s)); + ss += sprintf(ss, TT.f, dd); } - - if (i) printf("\n"); + *ss++ = '\n'; + xwrite(1, toybuf, ss-toybuf); } -- cgit v1.2.3