22

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.

Community
  • 1
  • 1
grautur
  • 29,955
  • 34
  • 93
  • 128
  • 7
    An important thing to remember is that slow is a relative term. It may be true that Ruby method calls are slow in comparison to other languages/environments, but perfectly acceptable for whatever particular task you might be doing. – ThomasW Jun 20 '11 at 01:29
  • Your understanding is right on the spot. – zneak Jun 20 '11 at 01:31
  • 4
    If are you comparing apples with apples, ie. Ruby vs other *dynamicaly typed interpreted languages* like Python, Perl, PHP, ... it really is not slower. We are talking about standard implementations, of course. In fact CRuby 1.9.2 has significantly faster method calls then both CPython 2.7 and 3.1. – David Unric Jun 20 '11 at 08:47
  • Vote to close as Not a Real Question. – user7116 Jun 21 '11 at 15:08

1 Answers1

20

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.

yfeldblum
  • 65,165
  • 12
  • 129
  • 169