On 29 July 2015 at 03:25, Andres Freund <and...@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/
<http://www.2ndquadrant.com/>
 PostgreSQL Development, 24x7 Support, Training & Services

Reply via email to