Thursday, May 1, 2008

Does Django really scale better than Rails?

I do quite a bit of Rails work. A very good bit actually...perhaps 60% of my professional time is now spent on Rails.

I like it, but have heard horror stories regarding Rails scaling. I personally haven't run into any problems, but most of our applications run internally at businesses serving hundreds of users...not many thousands or millions.

I recently read an article on highscalability.com about a Rails-based Facebook app that was serving up 300 million page views monthly. The article describes (and touts) the way they've scaled the application across 12 servers:
- 4 DB servers, 6 application servers, 1 staging server, and 1 front end server.
- 6, 4 core 8 GB application servers.
- Each application server runs 16 mongrels for a total of 96 mongrels. -
- 4 GB memcache instance on each application server
- 2 32GB 4 core servers with 4x 15K SCSI RAID 10 disks in a master-slave setup
Holy crap Batman...that's a lot of iron. I did a double take when I saw this....I mean, I know 9.6 million requests a day is a lot, but this is a very simple application...a Facebook toy...not what I would consider representative of a significantly complex web application (please someone correct me if I'm wrong). I mean, if 12 servers were used to serve up something like Facebook itself, I'd understand, but a widget for Facebook? Something smells.

Again, I'm no scaling expert, and I'm perhaps a little bitter that I've never had written an app that generated 9.6 mil page views daily, but that's beside the point. To me, what this says is that Rails may scale, but you'd better have lots of cash on hand to do so. Please, if this is expected of an app with this many hits, beit PHP or Java or Perl or Python or Ruby, please let me know.

While living in Ruby camp for the past several years, one common drum I hear thumping from the Python camp is that fact that Python, and particularly, Pylons and Django, are superior from a scaling perspective. However, while researching this today, I've had a hard time coming up with cold hard facts. I'm working on a small app I'd like to dream will catch on one day, and I'm considering ridding myself of the scaling problems early by switching to Django; that is, if Django really avoids the problems Rails faces.

I can't find any articles stating that it does (supported by facts and figures), nor can I find examples of heavily hit applications in the wild and what they're using. I do realize that the Washington Post uses Django, but I've also read that it's not used pervasively and mainly for smaller, lower-traffic sections of the site.

So, help a Python/Django newb understand...is there something inherently better about Python versus Ruby, or Django versus Rails, that makes the first scale and perform better than the latter?

Thanks guys. I appreciate your continued patience and commentary.

Wednesday, April 23, 2008

Ruby's Achilles heel...

Ruby is a beautiful language. Far more beautiful, in my very subjective opinion, than Python. However, beauty, as they say, is only skin deep. Below the skin lies the equally important bits: implementation, documentation, portability, performance and more.

I will expound my findings "beneath the skin" in future posts, but I ran across something today so telling of my general experience, syntax aside.

Look at these two urls. Both are from the official* standard library documentation for the respective language.

Absolutely no comparison. Python functionality is documented clearly...Ruby's documentation amounts to a method prototype and nothing more.

While this is just one example, I've run across it sooooooooo many times in the last three years. It's such a sad state of affairs that the official Ruby web site doesn't even *have* a documentation section of its own...it simply links to a collection of tutorials and third-party docs. Ruby-doc.org, which I pulled the above link from, takes the same approach, but includes the generated rdoc for the core and std libs. This rdoc is often, as demonstrated above, simply empty method prototypes.

It's simply tragic that such a useful and appealing tool has such shoddy documentation.

Tuesday, April 15, 2008

Functions versus blocks

In response to my last thread, someone answered with the following:

A problem I have with Ruby is that it has been infected with the same "everything must be in a class" nonsense that Java has. OOP is great, but sometimes having free-standing functions are more useful, especially functions that can be be applied to unrelated classes. "len" is a good example of this - because len is a function and not a method you can do things like this:

>>> x = ['abc', [1,2], () ]
>>> map(len, x)
[3, 2, 0]
and
>>> sorted(x, key=len)
[(), [1, 2], 'abc']
If 'len' was a method you would only be able to do this if all the objects that you want to take the length of inherited the 'len' method from a common base class (or mixin, in Ruby). This goes against the whole idea of duck typing.

So in this Python example, if I'm understanding it (and my Python studies) correctly, len is simply a reference to the function "object" that encapsulates logic that determines the length of something. Here's the official definition from the Python docs:

len(s):
Return the length (the number of items) of an object. The argument may be a sequence (string, tuple or list) or a mapping (dictionary).

Ok, so the logic contained in the function object pointed to be the reference "len" gives us the ability to determine the length of a string, tuple, list or dictionary. Great.

Why though is this any better than Ruby? To do the same thing in Ruby, you'd do something like:
irb> x = ['abc', [1,2], {} ]
irb> x.map {|one| one.length rescue nil}
[3, 2, 0]
So in the Python version, len is a builtin function that is passed to map...in Ruby, I simply create a block and pass it to map.

Perhaps the poster didn't realize you can use rescue in this way? It allows you to call length on *any* object and returns nil if that method exists. You could also do:
x.map {|one| one.respond_to? :length ? one.length : nil }
I'm sure one performs better than the other under the sheets, but I haven't tested to verify.

Is Ruby's approach better than Python? In this simplistic example, probably not. However, I think that Ruby's block syntax is more explicit and indicates meaning at the point of usage. Let's say I wanted to do more than just return length...what if I wanted to do some type checking as well?

In Python, I'd have to create a method first to wrap the desired functionality:
def conditional_len(obj):
if isinstance(obj, list):
return len(obj)
else
return None

a = [1, [2, 3], 4]
map(a, conditional_len)
In Ruby, it's (IMO) more obvious what we're trying to accomplish:
a = [1, [2, 3], 4]
a.map do |one|
if one.is_a? Array
return a.length
else
return nil
end
So I'm not sure I follow the argument here. Why exactly is Python's way advantageous compared to Ruby's? Can anyone shed some light?

Tuesday, April 8, 2008

Why I want to use Python, but don't...(yet)

Hello. I appreciate you stopping by. Let me tell you why this blog is here.

I'm a long-time developer. I have roughly 8 years of professional developer experience. I still read things daily by others that leave me in awe, but I think I hold my own pretty well. In other words, I'm good, but I haven't become so arrogant and obnoxious that the rest of the world look like idiots.

The road to here for me has been:

ksh -> C -> Perl -> C++ -> Java -> Php -> Java -> Ruby

I spent around three months doing Python in between Php and the second Java stint. I liked it...it was ok. But, the profession had other ideas for me.

It's been a fun ride. I've really appreciated things about each language I've used. But I finally found something in Ruby that really clicked. The language was intuitive; it could easily be held in your head, and what couldn't could be found quickly by exploring its very solid (though not perfect) introspection capabilities. There was a bit of a curve regarding rails, but that wasn't Ruby's fault...Ruby was just pretty ('cept for those damned dangling ends).

I really like Ruby the language...Ruby the experience...not as much. The docs are really bad right now in general across the Ruby space (I presume this will improve). The implementation is slow, but I honestly haven't done anything popular enough to feel threatened by it. Many of the libraries I need (eventmachine) are immature at this stage.

So many things lately have been pushing me towards Python. First, twisted has all the features I need for the network programming I'm working on. Second, I've read some really good things about Django and Pylons, and am preparing to work on a new web app. Third, Google's release of app engine today provides what I would consider some very strong validation for the Python community and for Python as a web programming language. Woohoo.

I actually started re-learning python a few months ago when I needed what Twisted had, but God help me I choked on the language itself. So many inconsistencies (__builtins__, two object models, .join, etc) that just didn't add up to a language with the beauty of Ruby.

I read the tutorial, bought Python in a Nutshell, read many of those chapters. But wow....I mean, really...Python seems so much more complex than Ruby. The chapter on OOP alone in Python in a Nutshell really twisted my head. And I've been doing OOP for years! Instead of a language like Ruby that you can entirely keep present in brain "ram", Python seems like a language that causes a significant amount of "swapping". In fact, I wonder if most Python programmers keep (or even understand) a very small subset of the language and operate in that space only. (which, if true, is complimentary to the language).

Listen, I want to explore Python. I want to want to use it. Right now I'm only driven by the fact that its libraries are solid and well documented, its implementation is fast, and it is widely used by two things I love (Linux and Google). If Ruby were in the same boat, there'd be no motivation to move. If Ruby had well-documented libraries (some day?), a good VM (soon) and was proven in big environments, I wouldn't be writing this.

So, here's my arm...please twist it. Help me to understand why Python is the way it is. Help me grok why people like it and use it so much. Help me understand why .join is where it is (nope...no chance in that). Help me feel good about investing the effort in to master Python. I want to join the community, but can't help but feel hesitant.