Merry Christmas everyone! In the spirit of Matz's tradition of Christmas
releases I'm releasing a gem today: New IO for Ruby!
Around Christmastime some 4 years ago, I started working on a library
called Rev which I would later rename to Cool.io, an event framework for
Ruby. Unfortunately Cool.io largely lingered in obscurity. Fast-forward to
today, and I'm not so sure about "event frameworks" in general. I'd like to
go in a different direction. It's another Christmas and I'm releasing
another I/O gem
nio4r is not an event framework. Instead, it's more like a mostly drop-in
replacement for Kernel.select with significantly better performance and
without the arbitrary limitations. nio4r uses high performance system calls
like Linux's epoll and *BSD's kqueue which lets you monitor large numbers
(i.e. > 1024) of Ruby IO objects with significantly less CPU usage than
Kernel.select. The main difference between nio4r and Kernel.select is that
nio4r keeps track of IO objects you're interested in between select calls
(keeping the state in the kernel itself as possible). This lets you not
only monitor significantly more objects, but eliminates the costly setup
associated with building the interest sets for Kernel.select.
Unlike Cool.io, nio4r also works on JRuby, and ties into the Java NIO
subsystem. In fact, nio4r is largely modelled off of the Java NIO API. Two
other implementations of nio4r are provided: a C extension based on libev,
and a pure Ruby version for those Rubies that don't support the MRI C
extension API. nio4r's goal is to provide as good as possible performance
on all Ruby implementations.
What is the relationship between nio4r and Cool.io? There isn't a specific
one yet, however nio4r could be used to replace Cool.io's existing native
extension, and in doing so would provide a path to JRuby support. If
someone was feeling particularly adventurous, they could potentially
rewrite EventMachine with nio4r instead of the buggy, crufty, largely
unmaintained byzantine 10,000 line C++ native extension EventMachine ships
Why nio4r? To a certain extent this is me wanting to scratch an itch I've
had for quite some time: providing a way to write evented code without a
large framework as a dependency. nio4r's primary goal is a high-performance
cross-Ruby implementation selector API for watching file descriptors and is
not intended to be an alternative to other Ruby IO enhancement projects
like Kinder Gentler IO (KGIO) which has mostly orthogonal goals.
My intended use case is bolstering the fledgling IO subsystem in my
concurrency library Celluloid. With nio4r as its underpinnings, Celluloid
should provide a great way to blend threaded and evented concepts. Every
Celluloid actor can function as a simplified "EventMachine", and as
Celluloid already wraps all events in fibers instead of exposing
callback-driven APIs, it should feel as simple and natural as using threads
+ blocking IO with significantly better performance.
My real hope is that Ruby implementers can help shape nio4r, ironing out
the kinks, then providing their own platform-native implementations that
can leverage better internal integration for more performance. Perhaps
nio4r could even be a standard API in Ruby 2.0.
More information on Celluloid: