Re: WIP: Make timestamptz_out less slow. - Mailing list pgsql-hackers

From David Rowley
Subject Re: WIP: Make timestamptz_out less slow.
Date
Msg-id CAKJS1f_46cttzZ+BD_hrVzqAw1KAuJxVKxCH8Q3HpfP2Z6Orjg@mail.gmail.com
Whole thread Raw
In response to Re: WIP: Make timestamptz_out less slow.  (Andres Freund <andres@anarazel.de>)
Responses Re: WIP: Make timestamptz_out less slow.  (David Rowley <david.rowley@2ndquadrant.com>)
List pgsql-hackers
On 29 July 2015 at 03:25, Andres Freund <andres@anarazel.de> wrote:
On 2015-07-29 03:10:41 +1200, David Rowley wrote:
> timestamp_out() = 2015-07-29 02:24:33.34 in 3.506000
> timestamp_out_old() = 2015-07-29 02:24:33.034 in 64.518000
> timestamp_out_af() = 2015-07-29 02:24:33.034 in 2.981000
>
> timestamp_out_old is master's version, the timestamp_out_af() is yours, and
> timestamp_out() is my one. times are in seconds to perform 100 million
> calls.

That looks good.

> So it appears your version is a bit faster than mine, but we're both about
> 20 times faster than the current one.
> Also mine needs fixed up as the fractional part is not padded the same as
> yours, but I doubt that'll affect the performance by much.

Worthwhile to finish that bit and try ;)

> My view: It's probably not worth going quite as far as you've gone for a
> handful of nanoseconds per call, but perhaps something along the lines of
> mine can be fixed up.

Yes, I agreee that your's is probably going to be fast enough.

> Have you thought about what to do when HAVE_INT64_TIMESTAMP is not defined?

I don't think it's actually important. The only difference vs float
timestamps is that in the latter case we set fsecs to zero BC.

Unless we want to slow down the common case it seems not unlikely that
we're going to end up with a separate slow path anyway. E.g. neither
your version nor mine handles 5 digit years (which is why I fell back to
the slow path in that case in my patch).

It occurred to me that handling the 5 digit year is quite a simple change to my code:

static char *
pg_uint2str_padding(char *str, unsigned int value, unsigned int padding)
{
char   *start = str;
char   *end = &str[padding];
unsigned int num = value;
//Assert(padding > 0);
*end = '\0';
while (padding--)
{
str[padding] = num % 10 + '0';
num /= 10;
}
/*
* if value was too big for the specified padding then rebuild the whole
* number again without padding. Conveniently pg_uint2str() does exactly
* this.
*/
if (num > 0)
return pg_uint2str(str, value);

return end;
}

We simply just need to check if there was any 'num' left after consuming the given space. If there's any left then just use pg_uint2str().
This keeps things very fast for the likely most common case where the year is 4 digits long.

I've not thought about negative years. The whole function should perhaps take signed ints instead of unsigned.

Regards

David Rowley

--
 David Rowley                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services
 

pgsql-hackers by date:

Previous
From: Michael Paquier
Date:
Subject: Re: tablecmds.c and lock hierarchy
Next
From: Amit Langote
Date:
Subject: Re: Transactions involving multiple postgres foreign servers