Null Object Performance

In implementing the NullObject pattern...

It seems to me this will be less time-efficient than directly checking for null because it requires an extra indirect method-call for each leaf node. (Not that efficiency is always the highest priority and calls will be often be overwhelmed by other factors.) -- MartinPool

And if for any reason you call several dummy methods instead of one null check, you obviously execute more code (and I-cache misses can be very expensive). --NikitaBelenki

A good principle of design is to keep the common case fast/simple. If the common case is that the thing being checked in null then it will generally be more efficient to implement the checks (though note exception below).

If the common case is that the thing will not be null then any time, however minimal, spent doing checks is wasted most of the time. Code without checks is likely to be simpler (to read) that that with the checks.

The important fact that makes the null pattern so important is that its cost is essentially *zero*. Thes is because the NullObject pattern is used in a context where you would be sending a message anyway. To reuse the unix analogy, instead of writing

  if ( $out != "/dev/null" ) echo "hello world" > $out

you simply write

  echo "hello world" > $out

A NullObject is not a null pointer, nor a nil reference. It is a full object, which conforms to the interface of the thing for which it acts as a Null. That interface may provide an isNull method. If it does, then call that method will be as expensive as any other. The greater code density of using a null object, and the reduction in the number of branches, may offset any advantage for cache performance. It would only be worth while checking "isNull" if performance analysis indicates that the null case is a common case, and that it is significant in the context of the system.


The "isNull" function would have to be polymorphic (virtual in C++), so it would have a non-trivial cost. You could avoid this cost by having a SingletonPattern NullObject and using a static inline function to check to see if any given object is the NullObject. Then, the test would be nearly as efficient as checking directly for the NULL pointer value. But you'd have to have extraordinarily severe performance constraints to justify this level of complexity. Still, even in this case, having a NullObject instead of using a NULL valued pointer makes it possible to optimize the one place where you want to check for "null" before calling, but to make virtual function calls to the NullObject in all other places in your code. So, NullObject is still the winner! ;-> -- JeffGrigg

Would the HotSpot compiler with dynamic inlining turn the message into a simple conditional?

In Smalltalk, message sends are often more efficient than conditionals. The more SpecialCase's involved, the greater the gain.

That's interesting to know. Of course in many other languages conditionals are more efficient than calls.

See PerformanceOfConditionalLogic.

Does anyone have any data, or are we just discharging fear?


View edit of August 28, 2007 or FindPage with title or text search