Blog

Apr 19 2007

Comments

Finally, a Ruby performance problem that bugs me

Lots of people are invested in the "Ruby is slow (but I don't care)" meme. Benchmarks establish that Ruby is just about the slowest serious language out there. Enthusiasts counter that Ruby is fast enough for most tasks, that programmer productivity is more important than processor productivity, and that there is nothing intrinsically slow about Ruby -- faster implementations are on the way.

Both perspectives are valid, but Avi Bryant makes an excellent point that has been mostly overlooked: Ruby's internal optimizations have made the language more difficult to understand and implement. But wait, you say. "Ruby optimizations? I thought the language was slow." Exactly. And because it is slow, much more of the core is written in C. This implementation choice leads to some unintuitive behaviors, although (as Avi's example demonstrates) you will not encounter problems unless you are doing very odd things. The more important effect is on language implementers. Avi argues that the JRuby team has to work much harder because the core is too large. The core is too large because of an optimization that was probably necessary at the time, but will seem premature in hindsight five years from now.

Except that the problem will be gone in five years. We can fix this one.

Apr 19 2007

Comments

...And another performance "issue"

Twitter's scaling needs are in the 11,000 requests/second and higher range (number from DHH). How is that working out, given that Twitter was developed in Ruby on Rails? If I can paraphrase the discussion so far:

Alex Payne (Twitter Developer): Ouch, scaling that big with Rails was hard, and we lost a lot of the elegance of ActiveRecord.

DHH: You could work with us to improve ActiveRecord to address this issue and continue to benefit from the elegance of the programming model.

People will draw their own conclusions from these perspectives. I personally live in the "make it work, then make it fast" camp. But the interesting point is not the discussion, it is the context: 11,000+ requests per second. Wow. 99% of all web application code will never need this scale. For most every project out there, advantage: Rails.

Apr 03 2007

Comments

Refactotum

Refactotum is a weekly series that teaches, by example, how to refactor code and contribute to open source projects. Here's how it works: We pick a project, download the code, and run the test suite. We then find code to refactor, testing all the way and taking notes. At the end, we convert the notes into essays or presentations, and contribute the code back to the community.

Each Refactotum project is time-boxed to four hours of dev effort. That's not much time; you can do it too.

Past refactorings include:

Mar 14 2007

Comments

Right tradeoff + wrong math = wrong tradeoff

The tradeoff between using a high-level languages and programming closer to the metal may seem, at first glance, to be a tradeoff between development costs and operating costs. With this argument, high level languages make development cheaper, but produce slower code which requires more processing power.

There are two big problems with this analysis. First, people often guess the math wrong by orders of magnitude. (Very few applications require a box for every ten users, regardless of development language.)

The second problem is that domain specific optimizations have a much larger impact on performance than language choice. Of course, in order to make domain specific optimizations, you need to have a clean code base. Continuous integration and performance metrics would help, too. All of these things are facilitated by programming in a higher level language.

In the book, we talk about scaling Rails applications from a baseline of hundreds of requests per second per box. That is plenty for a wide variety of applications, but not all. Do you know what performance your application really needs, and test for it?

Mar 14 2007

Comments

The J Plugin: Existing Rails Apps on JRuby

I am giving a JRuby presentation at the No Fluff, Just Stuff Symposium in St. Louis this weekend. With the recent announcement of JRuby 0.9.8, I am sure the first question on everyone's mind is "When will JRuby be production ready?"

To me, the only way to answer this question is to run some real apps in JRuby, and see what problems arise. However, most of the tutorials out there assume a green field application. That is unrealistic for enterprise developers like myself. We have dozens of existing Rails applications to support.

So, I set out to write a plugin that would let an existing Rails application run either in native Ruby or JRuby. I have open-sourced the result. You can add the J plugin to your Rails application with

  script/plugin install http://svn.streamlinedframework.org/j

J is very simple. Currently it only works with MySQL Rails apps, and only in *nix shell environments. Once you install it, all you do is

  rake j:setup
See the j.rake file and README for more usage info. Here's what I can tell you so far, having pointed J at three real-world web applications:

  • One of the three UIs ran correctly immediately. With the other two, I have uncovered different library behaviors between JRuby and native Ruby. I will take these over to the JRuby mailing list and report back on the solutions.
  • Testing tasks do not run, because Rails' databases.rake does not handle JDBC drivers yet. This should take only a few hours work, and I am hoping that someone has done it already.
All in all, I would say we are very close. Once we hammer out the few issues above, we can start continuous integration for our Rails development across both native Ruby and JRuby. Sweet.

Mar 06 2007

Comments

Teach Yourself Assembly Language in 0.0.2

Ever wanted the power that comes from knowing a programming language that is is only a tiny step removed from the underlying (virtual) machine instruction set? It has never been easier. All you have to do is wait 0.0.2.

Mar 01 2007

Comments

Feb 28 2007

Comments

FlexMock and Rcov: happy again

A few days ago, Jim Weirich sent me a beta of FlexMock (0.5.0.2) that includes a workaround for the dreaded rcov bus error. Before I even got finished testing it, Mauricio announced that Rcov was updated to 0.8, fixing the bus error. Sweet! FlexMock and Rcov are now playing nice again.

Now here is the next challenge. FlexMock's new_instances (the 0.5.0.2 replacement for any_instance) lets you mock all new objects of a class. As an implementation detail, I should note that it creates an eigenclass to do this. (Yes, I prefer the term eigenclass. Singleton is overloaded.)

The eigenclass should be an implementation detail, but because of a limitation of Ruby it is not. Eigenclass instances cannot be marshalled, so if you need to test objects that get thrown into a Rails session, the FlexMock approach will fail. Here's a challenge to you Rubyists out there: what's the best workaround for this particular problem? I think I have already decided on an approach but I would love to see what ideas the community comes up with.

Feb 27 2007

Comments

Rails Edge Notes

So, after completing a move to Edge Rails today, let me give you one piece of advice:

Explicitly declare your session options, and don't forget session_key. Without it, the new cookie performance enhancer blows up unceremoniously, and unless you want to spend a half hour searching dev.rubyonrails.org, you won't know why.

So, for example, in ApplicationController, you'd need:

  session :secret => 'abracadabra', :session_key => 'myapp_session'

And, voila! Problem solved.

Feb 27 2007

Comments

Ignoring the Big Problem

Well, the big move to Apache/Capistrano/Mongrel went well for, um, most of my internal sites that you don't care about anyway.

But, as the intermittent 4xx and 5xx errors coming out of relevancellc.com over the last few days indicate, things didn't go so well for the main public site. Basically this boils down to a Big Problem and a small problem:

  • Big Problem: Under even modest loads, the new stack blows up. Apache CPU usage skyrockets until we have to reset the box. There is some corner case in effect here, as both we and lots of other people are using this stack successfully in other deployments.
  • small problem: We have a lot of cruft from website moves in the past. We have old URLs from our Typo days, and old URLs from our Wordpress days, and on and on. Because these URLs do not match anything, they all pass through Apache and hit Mephisto. The small problem magnifies the load, which triggers the Big Problem very quickly.

I know how to fix the small problem--just watch the logs and add some RewriteRules. But that wouldn't be sporting, and besides, it would just make it harder for me to trigger the Big Problem. So I spent most of yesterday exploring the Big Problem. Some people would say that my explorations were unsuccessful, but I am a glass-half-full kind of guy. I now know a lot about various deployment issues that are not causing my problem.

This morning I took a different tack, and created the RewriteRules to solve the small problem. Surprise! With the small problem solved, the Big Problem doesn't happen anymore. (And even if it does, it happens rarely enough that the monit instance I installed yesterday is an acceptable workaround, plus a warning should the problem ever worsen.)

Sometimes it makes sense to ignore the Big Problem. Since I have isolated the problem so that it no longer does harm, there is no business need to solve the problem at all.

Popular Tags