I'm trying to read about Ruby performance, and came across this SO thread, where one of the answers mentions that "method calls, one of the most common operations in Ruby, are particularly slow."
Another thread mentions that "It does "late lookup" for methods, to allow for flexibility. This slows it down quite a bit. It also has to remember names per context to allow for eval, so its frames and method calls are slower."
Can someone explain in more detail why Ruby method calls are particularly slow, and elaborate on the second thread? I'm not totally sure what late lookup is or why it's slow, and I don't know what names per context means or how it relates to frames and method calls.
My (possibly incorrect) understanding is that since methods can be added or modified at runtime, the Ruby interpreter can never "remember" how to run a particular method, so it has to lookup the method every time while the program is running, and this is what is meant by method calls being slow. But corrections and more technical explanations would be great.
Dynamic languages like Ruby and Python are slower than static typed languages simply because they require lots of type checking at runtime.
Ruby development is fast and efficient For one thing, it's fast to write – projects, written with Ruby take 30-40% less development time than with other languages. This is because you need 3-4 times less code lines than in Java or Python.
There is a perception that Python is faster than Ruby, and this has often led teams to prefer it over Ruby for web development. The Ruby community is painfully aware of this, and Ruby has gotten way faster over the years. Now, in benchmarks, Ruby performs just about as well as Python, if not better.
When you call a method on an object, Ruby looks for the implementation of that method. It looks in the following places and uses the first implementation it finds: Methods from the object's singleton class (an unnamed class that only exists for that object)
Compiled languages often have fast method dispatch because the calling code knows an index into the class' vtable, which is an array of method pointers. After just a few pointer dereferences, the calling code can jump right into the method. The compiler create the vtable, and replaces every method name in the source code with the numerical index of the method in the vtable.
Dynamic languages such as Ruby often have slow method dispatch because the calling code has a name for the method, not a pointer (nor an index into an array containing the pointers). The calling code has to ask the object for its class, then has to ask the class if it has a method by that name, and if not, go on up the chain of ancestors asking each ancestor if it has a method by that name (this is what the compiler does in a compiled language, which is why the compiling is slow and the method dispatch is fast). Rather than a few pointer dereferences costing just a few machine instructions to invoke a method, a dynamic language must execute dozens to hundreds of machine instructions to search the object's class and all the object's ancestor classes for the method. Each class has a HashTable of names -> methods, but HashTables with string keys are an order of magnitude slower than arrays with integer indexes.
There are ways to optimize method dispatch in dynamic langauges, of course. In Ruby, that's what JRuby, Rubinius, and IronRuby are working on. But that's a subject for another question.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With