Wednesday, September 19, 2007

Rails Scaleability

Read a slashdot thread on Rails not scaling and now I need to weigh in from the safety of my blog. Let's do bullet points to help break down some of their arguments:

- PHP and Ruby are compariable
Sorry, you just can't do it. Ruby and Perl are comparable, Perl is probably better, who cares, let's move on.

- CakePHP is a great framework.
For me to poop on. Back before my Rails days I really wanted to like CakePHP. Seriously. I was a PHP ninja and the idea of MVC + data abstraction layer was a dream come true. But alas it was total crap. Weak community, annoying syntax (PHP's fault) and bugs. Next song.

- Rails is not thread safe
This is actually true, but rarely cited. Want to impress your friends, whenever they talk about Rails being slow because of Ruby, say "Who the fuck cares about Ruby? The Rails stack is not even thread safe you dumb bastard". What does that mean? It means a whole host of problems when it comes time to use your lovely self tested app. I"m not even talking about massive 2 billions requests per second sites, this will be bite you in the ass if you have 2 requests per second (given that one is significantly slower then the other).

- Ruby is slower then Python
So what, you think the bottle neck of your awesome facebook app is the CPU? How about I/O? You ever think of that? Full table scans, massive correlated queries, missing indicies, yeah, that's your problem chief. Unless you are doing some massive protein folding you better leave Ruby alone. Unless you are going to argue that Rails is not thread safe because of limitations in Ruby. Then you would be on to something.

- Google uses Java
Google is godlike in their programming ways. I seek only to collect what morsels of genius they donate to the community and not understand the terrible and mysterious ways they are contorting the web to their every whim. I am not google, you are not google, no one has ever been google and may never be again.

Tuesday, September 18, 2007

The silver bullet for zombie mongrels

Ok ok, so they are technically not zombie processes, but how could I resist such a great title.

I'm talking about mongrels that just stop responding to new requests. They are still up, ps does not tell you anything is wrong, monit thinks they are chugging along just fine, you can even telnet to them. But try to get a http response and it times out. Restarting the server fixes the problem every time.

This error state seems to be triggered randomly, however we saw it more with a overburdened mysql server running on the same box as the mongrels.

The trick, install the C based mysql driver. It's that simple, don't question it, just do it. Then curse yourself for not doing it sooner. You may even want to unleash a volley of nerf missiles on your coworker for claiming that we were using the C based driver all along.

Run this from the root of your rails app:
./script/console
Then this:
>> require_library_or_gem 'mysql'
If you don't see this:
=> ["MysqlField", "MysqlError", "Mysql", "MysqlRes"]
Unleash the fury.

How do you install the C based mysql driver?

1. Pray to your deity of choice that all required packages are installed.
2. Offer to trade the life of an office plant for a package management tool. (rpm is not package management, it's the root cause of anger management, see the difference?).
3. sudo gem install mysql
4. Replace that ficus you killed before office mates start asking questions.
5. Restart you rails apps

You do not need to change the rails environment.rb. If the gem is present, rails will find it.

If your god has forsaken you in steps 1-5 above just go grab the mysql RPM's your going to need.

Depending on distro, flavor and fat content, you will need some form of:
Headers and libraries
Shared libraries

Which can both be found on the mysql site.

Happy hunting.

Tuesday, September 11, 2007

When is / not division?

When you are using the wrong Ruby object.

Ruby seems innocent enough, but it's really doing a lot of 'object' work without you knowing.

Take the following rails example.

points = 0
points_possible = 100
points += quiz.points # points is 40, stored as an integer in the db,
percentage = ((points / points_possible) * 100) # evaluates to 0, WTF!

If we just give Ruby a little more direction by changing points to a float.

percentage = ((points.to_f / points_possible) * 100) # evaluates to 40, rock on