Latest on twitter:

Rack::Probing

It’s been a fun summer, but with its end comes the wind down of Google’s Summer of Code ‘09 (GSoC). Sounds like an opportunity to talk about Rack::Probe.

Rack::Probe packages a set of Dtrace probes for web applications in an easy-to-use and easy-to-love Rack middleware. Installation is a quick gem install rack-probe away.

As part of my GSoC project, Rack::Probe provides the data that makes profiling and monitoring a web app easier in a way that’s available to most Ruby web frameworks. The standardization that’s occurred on Rack for Ruby web frameworks is extremely helpful.

Let’s give an example a try. For our Rack-enabled app, we’ll be using the following:

Save it as a file somewhere, and run it with rackup filename. If you’d prefer to use your own Rails app, open up config/environment.rb and add in two lines:

Now that our app is running from our virtual law enforcement, let’s spy on it using dtrace to measure our request time. Our D script for doing just that is the following:

Save the script locally, and run it with dtrace -s script_filename. For as long as the script runs, it’ll be gathering data on the distribution of request times for each request that comes in. Feel free to ab -n1000 http://app.uri and go crazy. Control-C to abort the script and have it print out a distribution of the times.

Aside from its portability across frameworks thanks to its implementation as a Rack middleware, Rack::Probe’s benefits come from Dtrace itself. When we’re not actively probing, the overhead amounts to a single method call for each probe in our code, while the D language allows for a number of interesting investigations. For example, expanding our previous example to measure request time per path is as simple as:

While all of this is great and dandy, the catch comes from being limited in your OS choice: Dtrace only runs on Mac OS X, Open/Solaris, and FreeBSD.

Finally, I’d like to make special mention of the fact that all of this wouldn’t be possible without Chris Andrew’s great ruby-dtrace library. Be sure to buy him a beer if you ever get the chance.

Rack::Probe was written as the first stepping stone to Dtracy, which really took the brunt of my efforts this summer. While we wait for that upcoming blog post, feel free to check out Rack::Probe’s source code over at Github.

Proof that sometimes, throwing a small amount of money at something does make it look prettier.

Thanks to Julie Garcia for the logo.

Proof that sometimes, throwing a small amount of money at something does make it look prettier.

Thanks to Julie Garcia for the logo.

Haven’t ridden this horse in a while. Time to get back in the habit.

Haven’t ridden this horse in a while. Time to get back in the habit.

Before the Storm

Before the Storm

git push origin master

Finally pushed some code onto http://github.com/ecin/dtracy with a horribly uninformative README for starters. Won’t stay that way for long.

Explanatory post coming up next!

Sidetracked

I swear it was 1am two minutes ago…

So you suffer from ADD? Can’t focus on your work for more than a split second? Be embarrassed no longer, for now you have tenplustwo 1 (must run Mac OS X and growl to be eligible, no purchase necessary, void where prohibited):

ten + two. Get it? Ain’t Ruby neat?

Funny thing is, I spent a good two hours writing that2. Effort better be worth it! Time to get some things done.

We now return you to your regular GSoC ‘09 schedule.

1: I wish I had a link for you, but 10+2 and ten plus two bring nothing relevant up when googled for.

2: Actually, aside from writing out the short comment story, most of the time was spent looking into the best way to write a dynamic version of the script.

For the record, my mornings seem to be starting off at around midnight. More to come in the following hours.

Dancing Threads with Thin and Ebb

I’ve been cleaning up the code for a release later in the day, pondering over whether it’d be worth it to take Sinatra out of the picture and go pure Rack… doubtful. But enough of that!

Consider the JSONP long-polling problem. In order to keep a user’s experience constantly fresh with new content, we set up a javascript function that opens a request to the web server, and waits for new data to come pouring in. Once that’s done, it opens up another request and waits, ready to start the cycle all over. How Pavlovian.

Now this works great and all for data that isn’t constantly being generated. I don’t believe this to be our case, with Dtrace probes firing on all four cylinders to keep a tight grip on the pulse of our beloved server. So what’s the solution? I don’t know. I have some leads though, maybe. It’s late, ask me again in the morning…

However, while dealing with this, I did find out that Thin, Ruby web server of some that has been my trusty sidekick in development thus far, is single-threaded. Didn’t do my homework, is what happened. To make a short story shorter, I decided to give Ebb a try, got frustrated (it’s late, seriously) with the lack of documentation on getting it going with a Sinatra modular app, found out that Thin does have a threaded mode, found out that both web servers make use of a deferred() method to figure out which requests should be handed off to separate threads, and I’m heading to bed and may have more to say once I’m refreshed after some sleep.

Good night!

dtrace.c explained

An accompanying handbook to understanding what ruby-dtrace is doing.

epic_sleep()

In trying to package up the Sinatra app that serves the visualization code with some Dtrace-probe-consuming code, I came across a fun realization: running an instance of Dtrace::Consumer in a thread alongside the app doesn’t make for a fun evening.

In this case, the perpetrator wears the mask of Dtrace::Consumer#consume. Let me be more specific in pointing out where the banana peel has been placed:

Note the @t.sleep. You’d expect that to be Ruby’s built-in sleep command, perhaps. But don’t be fooled! Here’s its real definition:

The code ends up making a call to dtrace_sleep(), which is the equivalent of spreading sleeping powder all around. It will fall on threads running in the same Ruby process. And you may end up wondering why all your code suddenly chugs along at a half pace.

In the end, Dtrace::Consumer#consume is probably designed to be run in solitary confinement. Dtrace::Consumer#consume_once should solve my problems, just as soon as I figure out how to run it more than once…