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

Tom Lane <tgl@sss.pgh.pa.us>

From: Tom Lane <tgl@sss.pgh.pa.us>
To: Andres Freund <andres@anarazel.de>
Cc: pgsql-hackers@lists.postgresql.org, Thomas Munro <thomas.munro@enterprisedb.com>, Andrew Gierth <andrew@tao11.riddles.org.uk>, Alexander Kuzmenkov <a.kuzmenkov@postgrespro.ru>
Date: 2018-10-03T16:43:26Z
Lists: pgsql-hackers
Andres Freund <andres@anarazel.de> writes:
> On 2018-10-03 11:59:27 -0400, Tom Lane wrote:
>> I experimented with adding an initial check for "format is exactly %s"
>> at the top of dopr(), and couldn't get excited about that.  Instrumenting
>> things showed that the optimization fired in only 1.8% of the calls
>> during a run of our core regression tests.  Now, that might not count
>> as a really representative workload, but it doesn't make me think that
>> the case is worth optimizing for us.

> Seems right.  I also have a hard time to believe that any of those "%s"
> printfs are performance critical - we'd hopefully just have avoided the
> sprintf in that case.

Yup, that's probably a good chunk of the reason why there aren't very
many.  But we *do* use %s a lot to assemble multiple strings or combine
them with fixed text, which is why the other form of the optimization
is useful.

>> But then it occurred to me that there's more than one way to skin this
>> cat.  We could, for an even cheaper extra test, detect that any one
>> format specifier is just "%s", and use the same kind of fast-path
>> within the loop.  With the same sort of instrumentation, I found that
>> a full 45% of the format specs executed in the core regression tests
>> are just %s.  That makes me think that a patch along the lines of the
>> attached is a good win for our use-cases.  Comparing to Fedora 28's
>> glibc, this gets us to

> Hm, especially if we special case the float->string conversions directly
> at the hot callsites, that seems reasonable.  I kinda wish we could just
> easily move the format string processing to compile-time, but given
> translatability that won't be widely possible even if it were otherwise
> feasible.

Yeah, there's a mighty big pile of infrastructure that depends on the
way *printf works.  I agree that one way or another we're going to be
special-casing float8out and float4out.

BTW, I poked around in the related glibc sources the other day, and
it seemed like they are doing some sort of quasi-compilation of format
strings.  I couldn't figure out how they made it pay, though --- without
some way to avoid re-compiling the same format string over and over,
seems like it couldn't net out as a win.  But if they are avoiding
that, I didn't find where.

			regards, tom lane


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().