[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: LuaJIT FFI with libev
- From: Alban Linard <alban.linard@...>
- Date: Wed, 22 Apr 2015 15:17:04 +0200
Dear All,
i am trying to implement a Copas equivalent using libev (and maybe later
also libuv to perform some benchmarks).
For a first prototype, i used
[lua-ev](https://github.com/brimworks/lua-ev). It works quite well, but
does not seem to be maintained anymore.
Then, i came acroos
[evffi.lua](https://github.com/AlloSphere-Research-Group/alive/blob/master/master/ev.lua)
a LuaJIT FFI binding to libev. It is quite similar to lua-ev.
Maybe i understood wrong, but it seemed to me that the FFI binding would
be more efficient that the C module when used with LuaJIT.
So, i ran a simple benchmark [source
code](https://gist.github.com/saucisson/deb9048863386905e121#file-evffi-lua-L315).
This gist also contains the code for the FFI binding.
local ev = require "ev" -- or "evffi"
print (ev.version ()) -- 4.15 in both cases
collectgarbage "stop" -- only for "evffi"
local max = 10000000
local count = 0
local loop = ev.Loop.default
ev.Idle.new (function (loop, idle)
count = count+1
if count == max then
idle:stop (loop)
loop:unloop ()
end
end):start (loop)
local socket = require "socket"
local start = socket.gettime ()
loop:loop ()
local finish = socket.gettime ()
print (math.floor (max / (finish - start)), "idles / second")
Question 1: why do i get a "segmentation fault" when running luajit with
ev FFI on the example without `collectgarbage "stop"`?
The code for Idle handler is as below (the same applies to the modified
version shown after):
ev.Idle = {}
function ev.Idle.new (on_idle_fn)
assert (on_idle_fn, "on_idle_fn cannot be nil")
local ev_idle = ev_idle_t ()
ev_idle.active = 0
ev_idle.pending = 0
ev_idle.priority = 0
ev_idle.cb = on_idle_fn
return ev_idle
end
Question 2: when i run the benchmarks; the FFI version is faster
(3.212.945 idles/second vs 2.242.525 for lua-ev). But when using
sockets, i get the "too many callbacks" error from LuaJIT. So, i had to
update the code as below (shown for idle, but useless in the example):
ev.Idle.callbacks = {}
ev.Idle.on_idle = ffi.cast ("idle_cb", function (loop, idle, revents)
local address = tostring (idle):match "(0x%x+)$"
ev.Idle.callbacks [address] (loop, idle, revents)
end)
function ev.Idle.new (on_idle_fn)
assert (on_idle_fn, "on_idle_fn cannot be nil")
local ev_idle = ev_idle_t ()
local address = tostring (ev_idle):match "(0x%x+)$"
...
ev_idle.cb = ev.Idle.on_idle
ev.Idle.callbacks [address] = on_idle_fn
return ev_idle
end
It creates only one callback for each event type (idle, io, ...) and
does the dispatch in this callback. And with this, the performance drops
to 795.885 idles/second. Awful! And there is still the segmantation
fault when garbage collection is enabled.
So, i suspect i am doing something wrong... but what?
Best regards,
Alban Linard