s ago.)
This was my first time encountering the debate between an old, established language and a newer language that, while not as efficient in terms of processor speed, was a lot more efficient in terms of programmer time.
Flash forward ten years. C was firmly entrenched at AOL, as was I. But a new language was gaining prominence - Java. And the argument arose: should AOL make Java the language-of-choice for new applications?
Java had a lot of advantages over C. It’s a much easier language to use, and it is not vulnerable to some of the truly painful bugs that you can create in C. (I once saw a C project of a dozen people delayed for a week because of a misplaced semi-colon.) All of this translates into greater programmer productivity.
But Java is never going to be as efficient as C in terms of machine resources. Some of the features that make Java safe also cost processor cycles. This is independent of the compilers involved: even with the best compiler in the world, a Java program will not out-perform an equivalent C program.
Take one example: array bounds checking. In C, you can create an array of ten items, and then happily ask to access the eleventh item. C will allow this - the guiding principle of C is that the programmer knows what he’s doing, so even if it seems stupid, just do what the programmer says, dammit! This can cause all kinds of nasty effects in C. (The one-week delay that I mentioned above resulted from just such a bug.)
But whenever you access an array element in Java, Java checks that you are not going out of bounds. An attempt to access the eleventh item an a ten-item array will result in a Java error that pinpoints exactly where you went wrong. The bug will be found in a matter of minutes, not days.
This saves lots of programmer time. But doing those array bounds checks costs processor time - every time you access an array element in Java, it has to check to see that your access is in bounds. Processing time is sacrificed for programmer time.
AOL ran some benchmarks and found that a Java program would take around twice as much CPU time to run as the equivalent C program. But, especially given that the limiting factor on performance was usually I/O and not CPU, and given that programmer time had gotten more expensive while CPU time was constantly getting cheaper, this was a good trade-off. And so AOL adopted the policy that new development, unless there was a good reason to do otherwise, should be done in Java.
Now we come to the present, the inevitable moment when there is a new kid on the block, a new language that is challenging Java. It is easier to develop a web application in Ruby on Rails than in Java. Yes, Ruby is not as efficient in terms of processing time, but it is far more efficient in terms of programmer time. And processing time is not the limiting factor in most applications anyway.
In other words, it is exactly the same argument as we had ten years ago when deciding whether to stick with C or switch over to Java. Which in turn was exactly the same argument as we had ten years before that in deciding whether to stay with assembler or switch over to C. It is an argument that comes down to the question of what the limiting factor in development is: CPU time or programmer time. And in most applications, the answer is going to be programmer time.
(Speaking as a programmer, may I just say that I am very happy that programmers are more expensive than CPU’s. I hope this continues far into the future, with CPU’s getting cheaper while programmers get more expensive!)
Clearly, there are other factors involved. We shouldn’t dive into the new technology just because it is new. And it may prove that Ruby on Rails is not the wave of the future, in the way that C and Java once were.
But it is interesting to see the same old arguments being held over and over, and it’s instructive, when having these arguments, to remember how they turned out the last time around.
Add to Mixx!
* Filed under: Performance, Ruby on Rails |
* 10 comments
*
Ruby tidbit: When rescue doesn’t
Posted by Bill on July 31st, 2008
I learned a valuable lesson this morning, and I thought I’d share it with you. To deal with error conditions, Ruby includes, as do other languages, exception handling. This allows you to put all your code that might generate one or more errors in a block, and deal with any errors that do occur in another block. Far preferable to days of old when we had to check the return value of any call that may generate an error, and deal with it on the spot, each in unique fashion. Exception handling is much cleaner and more manageable:
begin
# Do stuff that may fail here
rescue
# Deal with those failures here
end
Most articles dealing with Ruby exception handling will tell you that the way to catch exceptions is with the “rescue” line. But it turns out, that’s only part of the truth. An example done in Ruby’s irb console:
irb(main):001:0> begin
irb(main):002:1* raise "Haha, you missed me!"
irb(main):003:1> rescue
irb(main):004:1> puts "No I didn't!"
irb(main):005:1> end
No I didn't!
So far so good. But now watch this:
irb(main):006:0> begin
irb(main):007:1* raise Exception.new("Haha, you missed me!")
irb(main):008:1> rescue
irb(main):009:1> puts "No I didn't!"
irb(main):010:1> end
(irb):7:in `irb_binding': Haha, you missed me! (Exception)
Woops! In that case, rescue really did miss it. But why? Doesn’t “rescue” mean rescue everything? I was surprised to find out that it doesn’t. One more example should clear things up:
irb(main):016:0> begin
irb(main):017:1* raise "Better luck next time!"
irb(main):018:1> rescue => e
irb(main):019:1> puts("I caught a " + e.class.to_s)
irb(main):020:1> end
I caught a RuntimeError
=> nil
irb(main):021:0> begin
irb(main):022:1* raise StandardError.new("Better luck next time!")
irb(main):023:1> rescue => e
irb(main):024:1> puts("I caught a " + e.class.to_s)
irb(main):025:1> end
I caught a StandardError
=> nil
irb(main):026:0> begin
irb(main):027:1* raise Exception.new("Better luck next time!")
irb(main):028:1> rescue => e
irb(main):029:1> puts("I caught a " + e.class.to_s)
irb(main):030:1> end
(irb):27:in `irb_binding': Better luck next time! (Exception)
Ah-ha! So while it seems that “rescue” would be the most generic way of dealing with exceptions of all kinds, it really isn’t. It will catch StandardError (of which RuntimeError is a subclass), but it misses Exception. The most generic exception handler turns to be “rescue Exception”:
begin
# Do stuff here
rescue Exception
# I will catch everything, even stuff that "rescue" misses
end
Lesson learned: unless you know the only thing you might have to deal with is StandardError or one of its subclasses, it’s better to use “rescue Exception” than just “rescue”. Nevermind documents that suggest that “rescue” catches exceptions; that’s true, but misleading - it really only catches certain kinds of them.
Add to Mixx!
* Filed under: Ruby on Rails |
* 7 comments
*
Scaling Rails
Posted by Joe on July 28th, 2008
Mixx is built using the Ruby on Rails framework. (Rails is the framework. Ruby is the language.) If you pay much attention to the internet tech world, this is likely to raise one big question: doesn’t that mean scaling problems?
Unfortunately, Twitter’s various problems with scaling and reliability have thrown up a lot of FUD around Rails. After all, Twitter is the best known large-scale Rails application on the web, and it has undeniably had problems with both scaling and stability. (Though having worked with the excellent engineers that Twitter just acquired with their purchase of Summize, I feel confident that their problems will soon be a thing of the past.) A common meme is that Twitter’s problems are due to Rails, and that therefore it is impossible to build a stable scalable application using Rails.
Since I’m the guy who chose to use Rails for Mixx, I obviously disagree. Let me tell you why.
(In the notes that follow, I’ll talk about both performance and scalability. I realize that these are not the same. However, they are closely related, and there’s FUD related to both around Rails, so I think it worthwhile to cover them both in this discussion.)
1. 80-90% of end-user response time has nothing to do with anything on the server - it’s in the design and implementation of the page.
This is the result of a study done by Yahoo!, as reported in Steve Souders’s excellent High Performance Web Sites (which I highly recommend - there should be a copy of this book in every web development shop). Most of performance is tied to issues like setting correct cache headers on images, reducing the number of objects on the page, and proper design of markup, CSS, and JavaScript. If you want your pages to load fast, look to your markup. (This is one of the many reasons that the first person I hired when I came on-board was Jason Garber, Mixx’s UI architect. And why I bought him a copy of the Souders book as soon as it was published.)
2. Performance on the server is mostly a matter of design of the data stores, not of application code.
A typical web application involves retrieving data from one or more data stores, manipulating it in some way, and rendering the page to contain that data. Of these steps, the one that is most likely to cause performance problems is the retrieval from the data stores. A poorly indexed database can cause major problems, and the biggest performance gains on a well-written application are going to involve faster data stores and a smart caching strategy. But these issues are not unique to Rails - they are common problems to all web applications, no matter what language is being used.
(While I know next to nothing about the Twitter architecture, I’m willing to bet that its scaling problems have to do with data store design, not application code. If Twitter were translated into another language without redesigning those stores, I expect that it would have the same problems. Building systems that require putting together data from multiple collections, with each user requiring a different set of data, is a tricky data design problem, no matter what the language.)
3. Rails supports scaling through duplication of application servers.
It’s easy to fire up as many instances of application and web servers as you need in Rails. Hardware scaling - throwing another box into the mix to partition load - is just as easy with Rails as it is with any other modern web application framework.
The limiting factor to this kind of scaling is the size of your database host - but that’s going to be the limiting factor no matter what application framework you have. And the same tricks used in other languages to overcome those limits work in Rails.
4. Rails supports scaling through partitioning of the application.
Another typical scaling approach involves partitioning the application into sub-applications, each of which runs on a separate set of servers. This can be done in Rails as easily as in any other language.
5. Rails optimizes for programmer time, not processor time - and that is the right choice.
I’m not saying that Rails is going to perform as well as languages such as Java. But Rails is optimized to make life easier for programmers, not computers. This is a common theme in the history of programming languages - a new language comes along that is easier for programmers, but less efficient in terms of processor time. There’s an entire blog post in that - and I promise to write it sometime soon.
6. It is easy to write naive Rails code that performs poorly. That’s why we you shouldn’t write naive Rails code.
Clearly, any language can be used to write bad, inefficient programs. But Rails, which abstracts out the database to make database access transparent to the programmer, probably makes it easier to write inefficient code. It is easy to slap together a quick Rails application without worrying too much about the database - that’s the great strength of Rails. But to get performance, you need to pay attention to the details. That isn’t too difficult, and I’ll blog sometime about how we’ve done it at Mixx. But it is necessary.
(I suspect that this is another cause of the bad reputation for performance that Rails has. People throw together a quick Rails application, taking advantage of its ease in programming, and are then surprised when it doesn’t perform. But while building an application can be easy, we aren’t yet at the point where building a complex and highly performant web application is easy.)
And there it is. At Mixx, we feel that Rails will serve us quite well as our application platform. In fact, we have effectively bet the company’s future on this belief. I do not expect to be proven wrong on this - while Rails is not a perfect platform in terms of performance, and there are a number of improvements that could help (another fertile ground for a blog post), for our application it performs just fine.
Add to Mixx!
* Filed under: Performance, Ruby on Rails |
* 5 comments
*
Welcome to the Engine Room
Posted by Joe on July 22nd, 2008
Welcome to the Mixx Engine Room, the blog of the Mixx engineering team. Over time, we’ll be writing posts describing various aspects of Mixx technology - how things are built, challenges that we’ve encountered in scaling, the reasons behind some of our technical decisions, and other details about our systems that we feel we can share with the world.
At Mixx, we’re strong believers in community. We’ve read The Cluetrain, and we believe in it. This blog will be the engineering team’s car on the Mixx Cluetrain.
But this blog is not like the movies. Here we roll the credits first. And so, without further ado, I give you the Mixx engineering team, listed by Mixx longevity:
- Raghu Somaraju is a backend developer here at Mixx, building the server code for several of our subsystems. When you first registered for Mixx, and the last time you logged in, you used Raghu’s code. In his pre-Mixx days, Raghu worked at Yahoo! in the News and Information group for three years, where he met Mixx CEO Chris McGill. After Yahoo!, Raghu worked at Juno Online in India and at an online ad agency start-up that, alas, did not make it.
- Joe Dzikiewicz (hey, that’s me!) wears many hats at Mixx, so it’s a good thing he has such a big head. As CTO, he manages the development and operations teams. As backend architect, he does overall architectural design of the backend systems. As a backend developer, he codes much of that design, including the initial work on the voting, submission, and categorization systems. Before Mixx, Joe was a systems architect at AOL for ten years, most of it spent in the Search and Community development teams. If you ever searched for something on AOL, chances are you used some of Joe’s code. When not writing Mixx blog, Joe blogs at www.drdzoe.com.
- Like most of the crew at Mixx, Jason Garber wears many hats, all of them stylish. His job as User Interface Architect implies that he has some sort of working knowledge of blueprints, AutoCAD, and spackle. This couldn’t be farther from the truth. Unless, of course, you think of HTML as a blueprint, CSS as spackling paste, and JavaScript as AutoCAD, but that’s a rather weak analogy. Poor analogies notwithstanding, Jason spends a good deal of time working with the rest of the Mixx team to ensure that everything that goes out the door is functional, attractive, and easy to use.
Prior to joining up with Mixx, Jason worked at a small design and marketing firm in Bethesda, MD, and did some time at AOL, most notably working on Ficlets, which won an award for Best CSS at this year’s South by Southwest conference. Between breaths, he is also involved in the local DC tech scene, organizing events, shooting photography, and playing in a rock and roll band.
- Nathaniel Collinsworth is Director of Operations for Mixx. His responsibility is the smooth running of all the technical infrastructure that the company needs. This umbrella covers a large number of disciplines; database, web server, mail, security, monitoring and alarming, business continuity, etc. It also includes the less challenging, but just as critical, needs of the office personnel. Nathaniel spends much of his days ensuring that Mixx can continue to scale to the needs of it’s growing user base. The first half of his career Nathaniel managed technology operations groups for non-technology companies, including non-profits, mining companies and the US Federal Government. The second half he has focused on the scalability and distribution of community applications on the web for AOL and for Mixx. He enjoys working at Mixx because he gets to use his broad range of talents to serve both the Mixx employees and our users.
- Bill Kocik also joins us from AOL, where he spent several years working in both Systems Operations and Software Engineering disciplines. At Mixx, Bill spends most of his time writing code that runs on the servers. Of note, he designed and implemented the Mixx API, and is largely responsible for the Site Mail feature, as well as once-per-day email notifications and the Google AdSense revenue sharing functionality.
- Doug March is a Senior Web Developer at Mixx. He spends much of his time bringing product designs and ideas to life. On the side, he helps dream up new features and dabbles in Search Engine Optimization. Doug started his career in the world of government consulting. Later, he found his niche and honed his skills at Revolution Health. In his free time he is usually on the links trying to collect that elusive 5th hole-in-one. When not enlightening you via the engine room, Doug blogs at http://doug-march.com.
So that’s us. Follow this space to learn more about the way we think, and the way we do technology.
Add to Mixx!
* Filed under: About Us |
* 8 comments
*
*
*
*
o Search for:
o
*
Browse the Engine Room
o About Us
o CSS
o JavaScript
o Performance
o Ruby on Rails
o Uncategorized
o User Experience
*
Archives
o December 2008
o October 2008
o September 2008
o August 2008
o July 2008
* The Mixx Blog
* Mixx Picks
*
Get to know us
o About Us
o FAQs
o Help
o Feedback
Langganan:
Posting Komentar (Atom)
Tidak ada komentar:
Posting Komentar