Inside the Objective-C Runtime
Subject:   dynamic dispatch cost?
Date:   2002-05-29 14:16:24
From:   eepstein
Response to: dynamic dispatch cost?

I dig into this a little more in the next article, but wanted to reply here.

The issue of performance that is at the heart of this question was an issue that had been frequently raised in the past on a theoretical level. On a practical level, due to the way that the Obj-C runtime is implemented, a dynamic method invocation takes about 1.7x a regular function calls (i.e., less that 2 function calls).

The longer version of that answer is that this impressive performance is the result of caching and the Obj-C runtime goes to some lengths to guarantee very fast cache resolution. Basically it's not method dispatch, but method "resolution" -- or finding the correct method implementation for a method invocation -- that takes time. Since this is basically static for a running app (only changes if/when a dynamic bundle is loaded) the lookup results can be cached and you get excellent performance. There is a one-time overhead for most methods of the first lookup. (This can be short-circuited for by having the runtime pre-load caches for specific methods.)

More to the point, really, is the basic question: when is performance an issue? The rough estimate in standard use is that only 10% of executable code ever benfits from being optimized for speed. Generally with GUI apps and DB apps and apps going over a wire, the bottle neck is not in the application. Heck, you can get reasonable web performance running interpreted Perl scripts. If, on the other hand, you need a Fast Fourier Transform to run on a tiny 20 MHz processor, you'll be needing to code the routines in assembler, as even C won't be fast enough.

Finally, looking at the places I've seen C++ code try to do dynamic things I've found a consistent pattern: Objective-C is ORDERS of MAGNITUDE FASTER than C++ !!! Shocking? True! Consider: the average Motif "callback" function takes an event. It then proceeds to compare some arbitrary attribute of the event (the tag, say, of a button that was clicked) in a huge if-then-else block. First this is simply bad, brittle code (though very common). Second it throws away at the outset the essential information that the window manager busily gathered for you: which widget was clicked. Third, it is really slow. 10x slower than Target-Action in Objective-C! And more brittle. And, well, dumber. Yet it is in almost every UI App I've seen. Which makes the final point : a modern computer is so fast that you can write really bad, slow code in C++ and it will still perform ok. Of course you could also write the app in Obj-C and have elegance and speed -- believe it or not, thanks to dynamism.

In my experience, Objective-C has never been a performance bottleneck. On occaission, I've found bits of code that needed to be optimized. On even rarer occaisions I've needed to code functions in pure C, but in those occaisions, it was obvious at design-time, as the problem being solved was computationally intense and performance was a system requirement.

Finally, as you dig into Obj-C and find the power of development that comes with it (simple things that are incredibly hard, tedious or impossible in C++, like: adding methods on a class high up in the hierarchy without needing to find/recompile all subclasses, changing inheritance locations without recompile all of your code, etc. etc.) you'll find that what dynamism buys you for the 1.7x overhead, is a great deal indeed.