[PATCH] unify itoa
Denis Vlasenko
vda.linux at googlemail.com
Tue Jul 11 14:44:48 UTC 2006
On Tuesday 11 July 2006 02:47, Rob Landley wrote:
> > The attached test program shows that snprintf is 2.5 times slower
> > than utoa. Operations done per second:
> > sprintf='12345678' count=27346
> > utoa_to_buf='12345678' count=69880
> > utoa='12345678' count=65934
> >
> > A few days ago I ran "hexdump | grep" over entire hard drive.
> > Took a long time. I wish hexdump was optimized a bit better...
>
> I haven't really looked closely at hexdump, but what does a base 10 utoa have
> to do with a base 16 hexdump?
This is a real-life example of a program which does a lot of
int -> string conversions, so that it actually mattered for me recently.
hexdump is of course using base 16 conversion. tcpdump could be
an example of a proc which does base 10 conversions, but I didn't
use it lately.
> The lookup table is a classic size/speed tradeoff, something BusyBox has
> traditionally come down on the "size" side of. Doing a write() on the result
> is going to be way slower than the actual conversion anyway. What actual
> bottleneck are you seeing?
>
> I definitely agree the bounds checking needs to be added, though. I'll do
> that now...
The version in current svn produces _most significant_ digits
if buffer is too small. IOW: utoa_to_buf_rob(100223,buf,3)=="10".
The usual practuce is to produce "23".
How about this modified version?
// 0x63 bytes
void utoa_to_buf_rob(unsigned n, char *buf, int buflen)
{
unsigned i, out;
if (buflen) {
buflen -= 11;
out = 0;
for (i=1000000000; i; i/=10) {
unsigned res = n / i;
n %= i; // gcc reuses remainder produced in division
if (res || out || i == 1) {
out++;
if (buflen >= 0)
*buf++ = '0' + res;
}
buflen++;
}
*buf = 0;
}
}
It's even a bit smaller. gcc is smart enough to know div instruction
produces the remainder also, and we get n %= i for free.
I still dislike the speed, i/=10 eats too much CPU...
--
vda
More information about the busybox
mailing list