Quantcast

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", .....]

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:

e=MC2

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).

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.