ryah ([info]four) wrote,
@ 2008-03-09 22:03:00
Previous Entry  Add to memories!  Tell a Friend  Next Entry
Entry tags:ebb

ev loop - ruby interface
I've made several attempts at rewriting the core interface between libev event loop and Ruby. The current implementation is the fastest:

    trap('INT')  { @running = false }
    FFI::server_listen_on_port(port)
    puts "Ebb listening at http://0.0.0.0:#{port}/"
    @running = true
    while FFI::server_process_connections() and @running
      if client = FFI::waiting_clients.shift
        process_client(app, client)
      end
    end
The key here is FFI::server_process_connections() which accesses the libev event loop, checks to see if there are any pending events, if so processes them - after all pending requests are finished it returns. If there are not any pending events the call blocks. The blocking is good because it prevents that while loop from running unrestrained. I have a timeout on libev which executes an event after 0.1 seconds just to get the function to return from it's blocked state occasionally.

Ruby's thread scheduler will not act while a C FFI function is being called. This setup is a bit precarious for multithreaded applications - they only get processing time when that loop runs.

It would be better if I could separate libev's loop from Ruby a bit more. I tried that today by putting ev_loop() in it's own pthread separated from the Ruby VM. The question then is, how does the Ruby side sit and wait for new connections? libev callbacks into the RubyVM cannot be executed from the outside like this. The solution I settled on was using a pipe with a nonblocking write side and a blocking read side. Thus the Ruby loop can gracefully block until new connections come in, but still free up the scheduler to handle other threads. This is how it looks
    notify_fd = FFI::server_listen_on_port(port)
    notifier = IO.new(notify_fd)
    puts "Ebb listening at http://0.0.0.0:#{port}/"
    
    while notifier.read(1)
      if client = FFI::server_next_client()
        process_client(app, client)
      end
    end
I like this a lot because it offers a clear interface. Unfortunately it just isn't very fast! Here it is compared to Ebb 0.0.4 and Thin:


Revert back or profile and hope for an obvious fix? Any suggestions?



Create an Account
Forgot your login or password?
Login w/ OpenID
English • Español • Deutsch • Русский…