-
-
Save tsafin/31cc9b0872b6015904fcc90d97740770 to your computer and use it in GitHub Desktop.
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
local ffi = require('ffi') | |
local clock = require('clock') | |
local builtin = ffi.C | |
local datetime_t = ffi.typeof('struct datetime') | |
local SECS_PER_DAY = 86400 | |
local DT_EPOCH_1970_OFFSET = 719163LL | |
local function datetime_new_raw(secs, nsec, offset) | |
local dt_obj = ffi.new(datetime_t) | |
dt_obj.secs = secs | |
dt_obj.nsec = nsec | |
dt_obj.offset = offset | |
return dt_obj | |
end | |
local function datetime_new_dt(dt, secs, frac, offset) | |
local epochV = dt ~= nil and (builtin.tnt_dt_rdn(dt) - DT_EPOCH_1970_OFFSET) * | |
SECS_PER_DAY or 0 | |
local secsV = secs ~= nil and secs or 0 | |
local fracV = frac ~= nil and frac or 0 | |
local ofsV = offset ~= nil and offset or 0 | |
return datetime_new_raw(epochV + secsV - ofsV * 60, fracV, ofsV) | |
end | |
-- create datetime given attribute values from obj | |
local function datetime_new(obj) | |
if obj == nil then | |
return datetime_new_raw(0, 0, 0) | |
end | |
local secs = 0 | |
local nsec = 0 | |
local offset = 0 | |
local easy_way = false | |
local y = 0 | |
local M = 0 | |
local d = 0 | |
local ymd = false | |
local h = 0 | |
local m = 0 | |
local s = 0 | |
local frac = 0 | |
local hms = false | |
local dt = 0 | |
local handlers = { | |
secs = function(_, v) | |
secs = v | |
easy_way = true | |
end, | |
nsec = function(_, v) | |
nsec = v | |
easy_way = true | |
end, | |
offset = function (_, v) | |
offset = v | |
easy_way = true | |
end, | |
year = function(k, v) | |
y = v | |
ymd = true | |
end, | |
month = function(k, v) | |
M = v | |
ymd = true | |
end, | |
day = function(k, v) | |
d = v | |
ymd = true | |
end, | |
hour = function(k, v) | |
h = v | |
hms = true | |
end, | |
minute = function(k, v) | |
m = v | |
hms = true | |
end, | |
second = function(k, v) | |
s, frac = math_modf(v) | |
frac = frac * 1e9 -- convert fraction to nanoseconds | |
hms = true | |
end, | |
-- tz offset in minutes | |
tz = function(k, v) | |
offset = v | |
end | |
} | |
for key, value in pairs(obj) do | |
handlers[key](key, value) | |
end | |
-- .sec, .nsec, .offset | |
if easy_way then | |
return datetime_new_raw(secs, nsec, offset) | |
end | |
-- .year, .month, .day | |
if ymd then | |
dt = dt + builtin.tnt_dt_from_ymd(y, M, d) | |
end | |
-- .hour, .minute, .second | |
if hms then | |
secs = h * 3600 + m * 60 + s | |
end | |
return datetime_new_dt(dt, secs, frac, offset) | |
end | |
-- create datetime given attribute values from obj | |
local function datetime_new_2(obj) | |
if obj == nil then | |
return datetime_new_raw(0, 0, 0) | |
end | |
local secs = 0 | |
local nsec = 0 | |
local offset = 0 | |
local easy_way = false | |
local y = 0 | |
local M = 0 | |
local d = 0 | |
local ymd = false | |
local h = 0 | |
local m = 0 | |
local s = 0 | |
local frac = 0 | |
local hms = false | |
local dt = 0 | |
for key, value in pairs(obj) do | |
if key == 'secs' then | |
secs = value | |
easy_way = true | |
elseif key == 'nsec' then | |
nsec = value | |
easy_way = true | |
elseif key == 'offset' then | |
offset = value | |
easy_way = true | |
elseif key == 'year' then | |
y = value | |
ymd = true | |
elseif key == 'month' then | |
M = value | |
ymd = true | |
elseif key == 'day' then | |
d = value | |
ymd = true | |
elseif key == 'hour' then | |
h = value | |
hms = true | |
elseif key == 'minute' then | |
m = value | |
hms = true | |
elseif key == 'second' then | |
s, frac = math_modf(value) | |
frac = frac * 1e9 -- convert fraction to nanoseconds | |
hms = true | |
elseif key == 'tz' then | |
offset = value | |
end | |
end | |
-- .sec, .nsec, .offset | |
if easy_way then | |
return datetime_new_raw(secs, nsec, offset) | |
end | |
-- .year, .month, .day | |
if ymd then | |
dt = dt + builtin.tnt_dt_from_ymd(y, M, d) | |
end | |
-- .hour, .minute, .second | |
if hms then | |
secs = h * 3600 + m * 60 + s | |
end | |
return datetime_new_dt(dt, secs, frac, offset) | |
end | |
local _ | |
local start = clock.time() | |
for _ = 1, 1e6 do | |
_ = datetime_new_dt(DT_EPOCH_1970_OFFSET, 60, 100000, 180) | |
end | |
print('datetime_new_dt', clock.time() - start) | |
collectgarbage() | |
collectgarbage() | |
start = clock.time() | |
for _ = 1, 1e6 do | |
_ = datetime_new{ secs = 60, nsec = 100000, offset = 180} | |
end | |
print('datetime_new', clock.time() - start) | |
collectgarbage() | |
collectgarbage() | |
local o = { secs = 60, nsec = 100000, offset = 180} | |
start = clock.time() | |
for _ = 1, 1e6 do | |
_ = datetime_new(o) | |
end | |
print('datetime_new(precreated)', clock.time() - start) | |
collectgarbage() | |
collectgarbage() | |
start = clock.time() | |
for _ = 1, 1e6 do | |
_ = datetime_new_2(o) | |
end | |
print('datetime_new_2(ifs)', clock.time() - start) |
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
✔ ~/datetime/tarantoolt/build [tsafin/gh-5941-datetime-v4 ↓·8↑·24|✚ 3…8⚑ 3] | |
12:39 $ ./src/tarantool ../../bench-hash-0.lua | |
datetime_new_dt 0.0030450820922852 | |
datetime_new 9.1180400848389 | |
datetime_new(precreated) 7.1469388008118 | |
datetime_new_2(ifs) 0.38320755958557 | |
✔ ~/datetime/tarantoolt/build [tsafin/gh-5941-datetime-v4 ↓·8↑·24|✚ 3…8⚑ 3] | |
12:39 $ ./src/tarantool ../../bench-hash-0.lua | |
datetime_new_dt 0.0036327838897705 | |
datetime_new 7.5975275039673 | |
datetime_new(precreated) 6.8448140621185 | |
datetime_new_2(ifs) 0.49595499038696 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment