Skip to content

Instantly share code, notes, and snippets.

@Buristan
Last active Jun 22, 2021
Embed
What would you like to do?
Simple benchmark for tarantool and cn:call()
local ffi = require "ffi"
-- require"jit.dump".start("-mx")
local NCYCLES = os.getenv("NCYCLES") or 3 * 1e6
------------------------------------------------------------------
-------------------------- Time measure --------------------------
------------------------------------------------------------------
ffi.cdef[[
struct timespec {
long tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
int clock_gettime(int clockid, struct timespec *tp);
]]
local C = ffi.C
local CLOCK_PROCESS_CPUTIME_ID = 2
local TIMESPEC = ffi.new('struct timespec[1]');
-- Returns clock_gettime sec, nsec.
local function now()
C.clock_gettime(0, TIMESPEC)
local sec = TIMESPEC[0].tv_sec
local nsec = TIMESPEC[0].tv_nsec
return sec, nsec
end
local function delta(t1sec, t1nsec, t2sec, t2nsec)
local dsec = t2sec - t1sec
local dnsec = t2nsec - t1nsec
if (dnsec < 0) then
dnsec = dnsec + 1e9
dsec = dsec - 1
end
assert(dsec >= 0, "delta seconds must be >= 0")
assert(dnsec >= 0, "delta nanoseconds must be >= 0")
return dsec, dnsec
end
local function print_delta(dsec, dnsec)
local runtime = tonumber(dsec) * 1e6 + tonumber(dnsec) / 1e3
print(string.format("%d mcs, %.1f K ps", runtime, NCYCLES/runtime*1e3))
end
local function bench(name, f, ...)
local ssec, snsec = now()
for i = 1, NCYCLES do
f(...)
end
local fsec, fnsec = now()
local dsec, dnsec = delta(ssec, snsec, fsec, fnsec)
assert(dsec >= 0, "delta seconds must be > 0")
assert(dnsec >= 0, "delta nanoseconds must be > 0")
io.stdout:write(string.format("%s: ", name))
print_delta(dsec, dnsec)
end
------------------------------------------------------------------
----------------------------- Prepare ----------------------------
------------------------------------------------------------------
-- Encoding should be as small as possible -- we just check call
-- value here.
local map = setmetatable({a = 1}, {__serialize = "map"})
local seq = setmetatable({1, 2}, {__serialize = "seq"})
local str = "s"
local dig = 1
local function ret_map()
return map
end
_G.ret_map = ret_map
local function ret_seq()
return seq
end
_G.ret_seq = ret_seq
local function ret_str()
return str
end
_G.ret_str = ret_str
local function ret_dig()
return dig
end
_G.ret_dig = ret_dig
local chunk = "return 1"
for i = 2,200 do chunk = string.format("%s, %d", chunk, i) end
local ret_mul, err = loadstring(chunk)
assert(ret_mul, err)
_G.ret_mul = ret_mul
local addr = "127.0.0.1:3803"
box.cfg{log_level = 0, listen = addr}
box.schema.user.grant('guest','read,write,execute','universe', nil, {if_not_exists=true})
local net_box = require "net.box"
local cn = net_box:connect(addr)
local call = cn.call
-- Let net_box become hot.
for i=1,1e3 do call(cn, "ret_map") end
for i=1,1e3 do call(cn, "ret_seq") end
for i=1,1e3 do call(cn, "ret_str") end
for i=1,1e3 do call(cn, "ret_dig") end
for i=1,1e3 do call(cn, "ret_mul") end
------------------------------------------------------------------
------------------------------ Bench -----------------------------
------------------------------------------------------------------
-- Unify results only once.
collectgarbage("collect")
collectgarbage("collect")
bench("Encode map", call, cn, "ret_map")
bench("Encode seq", call, cn, "ret_seq")
bench("Encode str", call, cn, "ret_str")
bench("Encode dig", call, cn, "ret_dig")
bench("Encode mul", call, cn, "ret_mul")
os.exit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment