NeverBlock, much faster IO for Ruby

Labels: , , , ,

At eSpace we have just released an alpha version of NeverBlock. A library that aims to bring evented IO to the masses. It does so by wrapping all IO in Fibers which handle all the async aspects and hides them totally from the developers.

Just as a teaser, here are some benchmarks of running PostgreSQL queries with and without NeverBlock



10x performance boost? how about that?

I am working on extending the NeverBlock library now, watch this space for great news soon

Comments (5)

Looks nice.
The only thing I can think of that would block would be the garbage collector [oh, and if anybody uses Net::HTTP within a controller or what not, or mechanize, etc.]

I did some teeny bit of work on making the garbage collector multi-threaded recently [and thus non-blocking]. Perhaps someday the project will present itself if I get around to it [1]. Non-blocking is definitely better, I'd agree. I like the potential this has. It might double the total processing speed, or perhaps even more.
Congrats.
-=R

[1] mentioned in here somewhere http://www.ruby-forum.com/topic/128068#new

The road map for NeverBlock includes providing replacements for stuff like Net::HTTP, utilizing Tony's async ruby socket replacements' code.

The garbage collector with its shameful pause is a real issue. Would love to see a generational one some day.

Anyway, if you monopolize cpu time with too many calculations then you will block the event loop anyway, that is why I am thinking of forked worker processes

Yeah this is similar but a little more hard-core than revactor.
I think the only thing asymy lacks [besides the bugs you pointed out] is error reporting--like if you do a query and the connection has already been dropped or what not.
One possibility would be to change the syntax from:

EventMachine::run {
c = Asymy::Connection.new(:target => "localhost",
:port => 13306,
:username => "user",
:password => "pass",
:database => "mysql")
c.exec("show databases") do |fields, rows|
pp fields
pp rows
end
}

to

c.exec("show databases") do |fields, rows, error_message|
end

Feel free to provide patches to the author--I think he accepts them :)

Yeah the GC stinks. You can decrease the GC impact by [in my case] about half if you apply skae's gcpatch [but that requires recompiling Ruby...heh]. If somebody wants to team with me it would be fun to build generational or threaded GC.

Some thoughts on neverblock:
If you do fork you will probably want ruby enterprise edition to cut back on wasted RAM. There's also optionally multi-threaded as mentioned earlier.

I also wonder if an option to 'not wait for a query to complete before continuing execution' would be useful. Ex: updates and inserts where you don't plan on using that information in the near future [since inserts tend to take quite a bit longer than queries]. Maybe useful :) Or, expanding on that, queries which can be performed 'on idle' or later, whenever you have some free CPU or what not. Possibly useful. Just some thoughts.

Also re: advertising.
If you can advertise neverblock as "an instant scaling dropin for rails 2.2" I think that would perk people's attention to it.

In order to get it to work you'd have to rewrite Thread.current[] to access the current fiber, I guess, and also link ActiveRecord to use neverblock and use a fibered driver [fibered mongrel or what not]. Something like that. I'm not sure of all the intricacies, but that's what might be most community useful.

Let me know how I can help.
Take care.
-=R

note: gcpatch: http://github.com/skaes/railsbench/tree/master/GCPATCH

I have a working AR implementation now. Only finalizing a few rough edges. I didn't like playing with Thread.current[] so I just replaced the AR methods I needed (mainly in Transaction). The good news is that it is a one line change for AR users.

Rails is just around the corner, but I am still tying things together and doing tests. But I am glad that Rails is (mostly) working with Ruby1.9

Regarding sending queries and ignoring the response this is surely a plus for things like logging. I believe it would be very easy to implement. I am using Fiber.current[] as the communication channel now.

I like your advertising idea, this would definitely attract attention. I will work on that and see what I can come up with.

Again, thanks for offering help, I more than willing to accept the offer :)