Last active
August 29, 2015 14:28
-
-
Save will/1b0ee6865472b8b30b46 to your computer and use it in GitHub Desktop.
more postgres time benchmarks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/tmp ➤ crystal build timebm.cr --release | |
/tmp ➤ ./timebm | |
2015-05-01 20:10:01 UTC | |
2015-05-01 20:10:01 UTC | |
2015-05-01 20:10:01 UTC | |
text 18636833.84 (± 1002412.33) 10.69× slower | |
binary span 60320068.97 (± 4530921.68) 3.30× slower | |
binary int 199241301.90 (± 17951824.75) fastest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class TimeDecoderText | |
def initialize | |
super | |
@curr = Pointer(UInt8).new(0) | |
end | |
def decode(value_ptr) | |
@curr = value_ptr + 0 | |
year = get_next_int | |
month = get_next_int | |
day = get_next_int | |
hour = get_next_int | |
minute = get_next_int | |
second = get_next_int | |
fraction = (@curr-1).value == '.'.ord ? get_next_int : 0 | |
sign = (@curr-1).value == '-'.ord ? -1 : 1 | |
offset = get_next_int * sign | |
milisecond = fraction_to_mili(fraction) | |
t = Time.new(year, month, day, hour, minute, second, milisecond, Time::Kind::Utc) | |
return apply_offset(t, offset) | |
end | |
private def get_next_int | |
return 0 if @curr.value == 0 | |
int = 0 | |
while @curr.value >= 48 && @curr.value <= 57 | |
int = (int*10) + (@curr.value - 48) | |
@curr += 1 | |
end | |
@curr += 1 unless @curr.value == 0 | |
return int | |
end | |
private def fraction_to_mili(frac) | |
if frac < 10 | |
frac * 100 | |
elsif frac < 100 | |
frac * 10 | |
elsif frac > 1000 | |
frac / 1000 | |
else | |
frac | |
end | |
end | |
private def apply_offset(t, offset) | |
if offset == 0 | |
t | |
else | |
t - TimeSpan.new(offset,0,0) | |
end | |
end | |
end | |
abstract class Decoder | |
def decode(value_ptr) end | |
private def swap64(ptr : UInt8*) : UInt64 | |
(((((((((((((((( 0_u64 | |
) | ptr[0] ) << 8 | |
) | ptr[1] ) << 8 | |
) | ptr[2] ) << 8 | |
) | ptr[3] ) << 8 | |
) | ptr[4] ) << 8 | |
) | ptr[5] ) << 8 | |
) | ptr[6] ) << 8 | |
) | ptr[7] ) | |
end | |
end | |
class TimeDecoderSpan < Decoder | |
def decode(value_ptr) | |
v = swap64(value_ptr).to_i64 / 1000 | |
Time.new(2000,1,1, kind: Time::Kind::Utc) + TimeSpan.new(0,0,0,0,v) | |
end | |
end | |
JAN_1_2K_TICKS = Time.new(2000,1,1, kind: Time::Kind::Utc).ticks | |
class TimeDecoderInt < Decoder | |
def decode(value_ptr) | |
v = swap64(value_ptr).to_i64 / 1000 | |
#Time.new(630822816000000000_i64 + (TimeSpan::TicksPerMillisecond * v), kind: Time::Kind::Utc) | |
Time.new(JAN_1_2K_TICKS + (TimeSpan::TicksPerMillisecond * v), kind: Time::Kind::Utc) | |
end | |
end | |
ptr = "2015-05-01 13:10:01.23442-07".cstr | |
#bytes = {0_u8, 1_u8, 184_u8, 9_u8, 144_u8, 219_u8, 139_u8, 244_u8} | |
#bptr = pointerof(bytes) as UInt8* | |
pgdate = -825324695007526656_i64 | |
bptr = pointerof(pgdate) as UInt8* | |
tdt = TimeDecoderText.new | |
tds = TimeDecoderSpan.new | |
tdi = TimeDecoderInt.new | |
p tdt.decode(ptr) | |
p tds.decode(bptr) | |
p tdi.decode(bptr) | |
require "benchmark" | |
Benchmark.ips do |x| | |
x.report("text") { tdt.decode(ptr) } | |
x.report("binary span") { tds.decode(bptr) } | |
x.report("binary int") { tdi.decode(bptr) } | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment