Typing
Monday, December 17th, 2007Those of you who regularly poll tech sites will certainly have heard of ruby in the last two years. The fanboyism of the average ruby zealot is not ignorable and it’s impossible to escape from it.
Anyway, I won’t write about ruby and its users today (though maybe they should broaden their horizons and try something real).
However, a year ago during the big RoR hype (remember 37 signals?) plenty of web developers jumped into the ruby water. I have the impression lots of them did never use a web framework before and were that amazed about the productivity boost they experienced, they just couldn’t stop writing about their great discovery. This affected the typical discussion and made things even worse.
ruby ownez teh noobs OMG
Fortunately, nowadays that is followed by the classical
ZOMG RUBY IS TEH SLOW
and most of the ruby developers got uncovered anyway by Steve Yegge’s
Ruby fans seemed like ferret owners. They could go on and on about how much they adored their beady-eyed albino stretch-limo rats, and how cute they were, but we all knew they were just looking for attention.
Anyway. Where was I going with this? Oh yes, if you are bored and search for entertainment among ruby flame wars on the internet you will certainly read about problematic DB design, scalability and performance issues. As for the performance issues, ruby’s type system is blamed for the performance issues it has. But what is a type system?
Type system
When a program gets written, the developer normally has to deal with data. This may be anything from a simple integer to more complex data structures. Those values are stored as bytes in the memory. As you can imagine, it’s not very funny to deal with a bunch of bytes so people started to define “types” which represent specific byte arrays. Hence, instead of an array of four eight bytes, a variable with type “integer” can be used. After that everybody could pass his new and fancy types to functions but it was still a bit of a hassle.
Later somebody came up with the idea of adding functions to those types and called them “Objects”.
However, when you move around your variables on the stack, a mechanism is required which ensures that the type of your variables matches the type expected (We have a function whose only parameter is an integer. It must be forbidden that a string gets passed. Otherwise strange things would happen when the first few bytes of the string passed get interpreted as an integer). The thing which makes sure that this doesn’t happen is a Type Checking System.
There are several ways to implement such a system. The verification may occur when the program gets compiled or on demand when the program is running.
Static typing
The compiler makes sure that the type-contracts don’t get violated. This means type errors get detected very early and the compiler can also perform further optimizations. The errors detected depend on how powerful the type system is though.
In a statically typed language, refactoring tools are easier to implement and more accurate. The contract between caller and callee is clearer but this normally leads to more verbose expressions. Limitations in the typing system exist and need to explicitly overridden by the developers with casts or similar constructs. Static typing is used in Java or Haskell.
Dynamic typing
The type verification is done during run-time. This leads to some runtime overhead, allows more flexibility for the developer though.
var i = 3; var j = "33"; var k = i + j;
Although a string is used for “j”, it’s obvious enough for the runtime what we are trying to do. More code can be written in less time like this but there is no compiler which makes sure that the statement can be executed later. Dynamic typing is used in languages like Python and Lisp.
Duck typing
Duck typing is a subset of dynamic typing. Rather than requiring a special type of a variable, just the actually used aspects are demanded. The type itself doesn’t matter. When the execution environment discovers during run-time that the required method is not implemented in the passed variable, the application stops with a run-time error.
Ruby
Ruby uses duck typing. The problem this language has is that those duck type checks need to be performed on every function call (and it’s really a problem. Check out the release notes of new versions and you will see they just talk about performance. Or watch the community get thrilled when there is a release of a fast implementation)
Ruby needs to scan and analyze the object, find the function which should be called, generate the according cpu instructions and execute it. In a statically typed language, all those steps can be precomputed by the compiler. And guess what, Ruby has to redo those validations on every function call! Unfortunately it’s just pretty common for developers to call functions all the time. Now just imagine how slow recursion is.
Thus the anti-ruby guys have certainly a point with their performance argument. It *is* slow.
However, it should also be considered that not everybody builds a website which attracts half the population on earth and shorter development cycles are worth more than an upgrade of your server.
