Re: Performance improvements for src/port/snprintf.c

Alexander Kuzmenkov <a.kuzmenkov@postgrespro.ru>

From: Alexander Kuzmenkov <a.kuzmenkov@postgrespro.ru>
To: Tom Lane <tgl@sss.pgh.pa.us>, pgsql-hackers@lists.postgresql.org
Date: 2018-09-07T18:53:27Z
Lists: pgsql-hackers
I benchmarked this, using your testbed and comparing to libc sprintf 
(Ubuntu GLIBC 2.27-0ubuntu3) and another implementation I know [1], all 
compiled with gcc 5.4.0 with -O2. I used bigger decimals in one of the 
formats, but otherwise they are the same as yours. Here is the table of 
conversion time relative to libc:

format                                 pg      stb
("%2$.*3$f %1$d\n", 42, 123.456, 2)    1.03    -
("%.*g", 15, 123.456)                  1.08    0.31
("%10d", 15)                           0.63    0.52
("%s", "012345678900123456789001234    2.06    6.20
("%d 012345678900123456789001234567    2.03    1.81
("%1$d 0123456789001234567890012345    1.34    -
("%d %d", 845879348, 994502893)        1.97    0.59

Surprisingly, our implementation is twice faster than libc on "%10d". 
Stb is faster than we are with floats, but it uses its own algorithm for 
that. It is also faster with decimals, probably because it uses a 
two-digit lookup table, not one-digit like we do. Unfortunately it 
doesn't support dollars.

1. https://github.com/nothings/stb/blob/master/stb_sprintf.h

-- 
Alexander Kuzmenkov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company

Commits

  1. Improve snprintf.c's handling of NaN, Infinity, and minus zero.

  2. Rationalize snprintf.c's handling of "ll" formats.

  3. Provide fast path in snprintf.c for conversion specs that are just "%s".

  4. Make assorted performance improvements in snprintf.c.

  5. Set snprintf.c's maximum number of NL arguments to be 31.

  6. Always use our own versions of *printf().