On Tuesday 09 October 2007 20:48, Heikki Linnakangas wrote:
> The new linux code is slightly but not much faster than the old one
> (3.04s vs 3.16s),

Test on my machine (three runs)

$ time ./sprintf-linux
./sprintf-linux 10-70-110
user    0m2.018s
user    0m2.024s
user    0m1.997s

$ time ./sprintf-linux-new
./sprintf-linux-new 10-70-110
user    0m1.839s
user    0m1.825s
user    0m1.817s

Re Linux printf speed:
I measured 10% run time reduction in top caused by faster generation
of /proc data. This 10% includes all overhead of printf(), read(),
copying data from kernel to userspace, parsing it in top etc.

Microbenchmark in userspace (running number() in a tight loop)
gave x3 performance increase.

> but it does beat glibc (5.20s) by a wide margin. 
> However, preparsing the format string in gcc still beats the linux
> version hands down (0.82s).

You preparse "%d-%d-%d"? Into what?

I am from "small is beautiful" camp. I don't like "code growth
for everyone for the benefit of 5% of code which really needs
that last bit of speed" policy.

I hate 80MB+ Oracle executables with passion.

What problems do you see with this:

sprintf(char *dst, const char *fmt, ...)
{
  char *d;
  char *p = strchr(fmt, '%');

  /* Literal string? */
  if (!p) {
    d = stpcpy(dst, fmt);
    return d - dst;
  }

  va_start(ap, fmt);

  /* Copy leading literal prefix */
  d = mempcpy(dst, fmt, p - fmt);
  fmt = p;

  /* Fast path for "...%s...%s...%s..." */
  while (p[1] == 's') {
    char *q = va_arg(ap, char*);
    d = stpcpy(d, q);
    fmt += 2; /* skip %s */
    p = strchr(fmt, '%');
    if (!p) {
      d = stpcpy(d, fmt);
      return d - dst; 
    }
    d = mempcpy(d, fmt, p - fmt);
    fmt = p;
  }

  ...continue with original sprintf code...
}

It's small code increase, only in ONE place,
catches even cases where format is not constant.
--
vda

Reply via email to