Disabling callbacks in an ActiveRecord data migration
January 29th, 2009
It’s often useful to disable ActiveRecord callbacks such as :after_save when migrating data. It’s rather easy to do:
Foo.after_create.clear
Foo.after_save.clear
... migration code ...
If you only need to disable certain actions, it’s also trivial:
Foo.after_save.reject! {|callback| callback.method.to_s == 'some_method_name' }
This sort of thing should never be used in application code, if you’re doing this then your model is broken. However, it’s great for data migrations.
IRC question of the day
January 9th, 2009
Question:
_adc: I'm doing compiling some reports on various database records based in whatever model the user chooses... Is there a better way to figure out which models are in existence than http://pastie.org/356630 ? _adc: I'm looking for an array of all models currently in existence.
Answer:
ActiveRecord::Base.subclasses_of(ActiveRecord::Base)
~/projects/learnhub$ ./script/console
Loading development environment (Rails 2.1.1)
>> ActiveRecord::Base.subclasses_of(ActiveRecord::Base).collect {|c| c.to_s }
=> ["CGI::Session::ActiveRecordStore::Session", "ContactPostCreationNotification", .....]
Three simple scripts for Passenger (mod_rails) management
December 31st, 2008
Phusion Passenger is the best option for hosting Ruby based web apps (anything that uses Rack is compatible). When used with Ruby EE to serve Ruby on Rails applications it will consume up to 33% less memory than other servers such as Mongrel.
Not everything is kittens and rainbows however, as Passenger won’t prevent your app from choking your server if you consume too much memory (via memory leaks in your app, etc). Schedule this script to run every couple of minutes to kill any Passenger processes are consuming too much memory. Passenger will automatically start new ones as needed. You’ll have to figure out for yourself how much is “too much”. In my case it’s 200 MB.
It’s also useful to know how many process Passenger is using, so you can increase the MaxPoolSize when traffic increases. I use Munin to track system statistics and have written two wrappers around the Passenger system tools. The first wraps passenger-memory-stats and the second wraps passenger-status
The result are graphs such as these:

Munin graphs can be extremely helpful when tracking down system performance issues. I highly recommend it.
TexHub: A math equation service
December 29th, 2008
Carsten and I recently launched TexHub which is a little service for serving up latex equations as images. It’s pretty simple, just Base64 + URI encode latex string and append it to a URL. It’s extracted from our math equations feature on Learnhub
For example:
A more complex example: F(x) = \\int_{-\\infty}{a} f(t)dt + \\int_{a}^{x} f(t)dt
We haven’t done much with the front end yet as we’ll primarily be using it as a service, so the focus has been on speed. I wrote the web interface using Sinatra which turned out to be perfect for this sort of app. I plan on writing more micro apps in the future with Sinatra, perhaps the next thing will be the Ruby version of Tilomino which has been sitting untouched for two years….
Irony
August 25th, 2008

Glad to know that MS still considers that IE 6.0 is a ‘recent browser’ (it’s 7 years old, which is ancient in internet years).
Ruby VM shootout on Rock, Paper, Scissors!
August 11th, 2008
Update: I’ve added benchmark numbers for JRuby 1.1.3
I’ve been messing with RubyRPS (Rock, paper scissors) lately, it’s a ton of fun! I thought it might be cool to benchmark the progression of Rubinius, and that little experiment turned into a full blown ruby interpreter shootout. Sure, this is hardly fair since RPS doesn’t use much in the way of complicated stuff (lots of loops over array, etc), but most benchmarks are bullshit anyways. I just want my RPS bots to run fast!
Here are the versions I tested.
- ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0] (macports)
- ruby 1.8.7 (2008-06-20 patchlevel 22) [i686-darwin9.3.0] (macports)
- ruby 1.9.0 (2008-03-01 revision 15664) [i686-darwin9.4.0] (macports)
- ruby 1.9.0 (2008-07-25 revision 18218) [i686-darwin9.4.0] (snapshot 1.9.0.3)
- Rubinius 0.9.0 (ruby 1.8.6 compatible) (ffb998bf5) (08/07/2008) [i686-apple-darwin9.4.0] (from trunk)
- JRuby 1.8.6 (2008-08-07 rev 6555) [i386-jruby1.1.1] (macports)
- MacRuby version 0.3 (ruby 1.9.0 2008-06-03) [universal-darwin9.4] (downloaded binary)
Benchmarking is rather simple:
# time ruby ./run.rb
# time ruby1.8.7 ./run.rb
# time ruby 1.9 ./run.rb
# time rubinius ./run.rb
# time jruby ./run.rb
# time macruby ./run.rb
| Interpreter | Memory Usage | Real | User | System |
| Ruby 1.8.6 | 3MB | 0m36.183s | 0m35.426s | 0m0.241s |
| Ruby 1.8.7 | 10MB | 0m17.778s | 0m17.086s | 0m0.154s |
| Ruby 1.9.0 | 11MB | 1m17.092s | 0m53.843s | 0m22.234s |
| Ruby 1.9.0.3 | 10MB | 0m10.350s | 0m9.911s | 0m0.111s |
| JRuby 1.1.1 | 28MB | 0m18.023s | 0m16.198s | 0m0.417s |
| JRuby 1.1.3 | 28MB | 0m18.622s | 0m17.482s | 0m0.321s |
| Rubinius | 26MB | 0m42.836s | 0m41.556s | 0m0.479s |
| MacRuby 0.3 | 476MB | 0m42.471s | 0m40.302s | 0m0.987s |
How about a threaded run just for fun?
# time ruby ./run.rb --threaded
# time ruby1.8.7 ./run.rb --threaded
# time ruby 1.9 ./run.rb --threaded
# time rubinius ./run.rb --threaded
# time jruby ./run.rb --threaded
# time macruby ./run.rb --threaded
| Interpreter | Memory Usage | Real | User | System |
| Ruby 1.8.6 | 4MB | 1m12.343s | 1m9.703s | 0m0.695s |
| Ruby 1.8.7 | 13MB | 0m18.019s | 0m17.561s | 0m0.188s |
| Ruby 1.9 | 13MB | 1m18.341s | 0m54.516s | 0m21.947s |
| Ruby 1.9.0.3 | 13MB | 0m10.505s | 0m10.013s | 0m0.126s |
| JRuby 1.1.1 | 34MB | 0m17.048s | 0m22.013s | 0m1.890s |
| JRuby 1.1.3 | 31MB | 0m15.630s | 0m22.580s | 0m1.475s |
| Rubinus | 52MB | 0m43.745s | 0m41.893s | 0m0.591s |
| MacRuby 0.3 | Error! | stack level too deep (SystemStackError) |
Conclusion
Ruby 1.9 runs RPS really fast. You may have to compile it yourself for now if you’re on a Mac, since the version in Macports does have some issues. Also, I’d recommend that anyone who is still running Rails apps on 1.8.6 to move to 1.8.7 to for an increase in speed. We’ve been using 1.8.7 to run Learnhub for a few weeks now and have noticed a decrease in memory leaks as well. Be sure to check for compatibility with your Rails app though, 1.8.7 doesn’t work with some older versions of Rails.
Surprises
I was surprised that Jruby did so well. It performs just as well as MRI 1.8.7 (with about double the memory usage). I was expecting the interpreter startup time to hold Jruby back, but that didn’t turn out to be the case. Rubinius also performed a bit better than expected (they’ve been working on correctness rather than speed thus far). It wasn’t much slower than MRI 1.8.6, although it consumed far more RAM. My understanding is that the VM is currently being rewritten, so I’ll run a few more tests when it’s released.
MacRuby is also an interesting project, with a goal of porting MRI 1.9 to run directly on top of Mac OS X core technologies such as the Objective-C common runtime and garbage collector, and the CoreFoundation framework. It’s very much a work in progress at this point.


