AsyncRecord: Non-blocking database access for Ruby

Chris Moos

Two weeks ago I developed my first event-driven web framework for Ruby, Fastr. It helped me understand why running a web framework in an event loop is so natural.

As I continued to tackle more features in Fastr, it was time to tackle persistence – notably, database access.

AsyncRecord is/will be an ORM, similar to ActiveRecord – with one major difference – it doesn’t block. AsyncRecord currently uses em-mysql to access a MySQL database.

How it usually works

In most ORMs, when you attempt to access the database, everything in that thread will block until a response is received. This means that you waste time – just waiting. The CPU may be idle, but you cannot handle any more requests. (Typically you start multiple instances of your application to get past this, unfortunately each instance requires more resources on your server)

How AsyncRecord works

When you access something in the database with AsyncRecord, the request is sent to the database server, but control returns to the application immediately after the packet(s) are sent. When the server responds, which could be 20ms or 200ms later, a callback that you specify is invoked.

One important thing about accessing a database asynchronously, especially in web frameworks, is the ability to defer a response. Fastr has built-in support for deferred responses, a-la EventMachine/Thin.

A deferred response is when you tell the web server that you will send data to the client some time in the future, and the server is free to handle more requests until you are ready to respond.

Benchmarking

As I was implementing AsyncRecord, I knew it would be faster – but I wasn’t sure by how much. I setup a very simple Rails 2.3.5 application, as well as a Fastr application (from the latest source).

My goal was to make an application that has a single page, which shows 5 usernames from the database.