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