Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Benchmark of LuaJIT FFI callbacks from C into Lua
local ffi = require("ffi")
ffi.cdef[[
typedef void (*cb)(void);
void call(int n, void (*)(void));
void loop(int n);
void func(void);
]]
local callback = ffi.load("./callback.so")
local timeit = require("timeit")
local function lfunc() end
print("C into C", timeit(function(n)
callback.call(n, callback.func)
end))
print("Lua into C", timeit(function(n)
for i = 1, n do callback.func() end
end))
print("C into Lua", timeit(function(n)
callback.call(n, lfunc)
end))
print("Lua into Lua", timeit(function(n)
for i = 1, n do lfunc() end
end))
print("C empty loop", timeit(function(n)
callback.loop(n)
end))
print("Lua empty loop", timeit(function(n)
for i = 1, n do end
end))
void call(int n, void (*f)(void)) {
for (int i = 0; i < n; i++) {
f();
}
}
void loop(int n) {
for (int i = 0; i < n; i++) {
/* prevent compiler optimizations from skipping loop entirely */
__asm__("");
}
}
void func(void) {
}
--- call a function with a repeat count argument.
-- Takes a single argument, which is a function which in turn takes one argument,
-- a repeat count. The function is called with increasingly large repeat counts
-- until it takes at least a certain amount of time to run, and is then called four
-- more times with the same repeat count, with the minimum elapsed time recorded.
-- Modeled loosely on Python's timeit, except the function passed in is responsible
-- for doing the actual repetition.
return function(func)
local reps = 10000
local elapsed
repeat
reps = reps * 10
local start = os.clock()
func(reps)
elapsed = os.clock() - start
until elapsed > 0.05 or reps >= 1e9
for i = 1, 4 do
local start = os.clock()
func(reps)
elapsed = math.min(elapsed, os.clock() - start)
end
return ("%7.3f nsec/call"):format(elapsed / reps * 1e9)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.