ifTrue:ifFalse: Faster than ifNil:
This came as a bit of a surprise to me at first. I remember now hearing somewhere that ifTrue:ifFalse: was highly optimized in VisualWorks. But the results of this test surprised me.
I had an idea that replacing the lazy initialize pattern:
myVar ^myVar isNil ifTrue: [myVar := 1] ifFalse: [myVar]
with:
myVar ^myVar ifNil: [myVar := 1]
would produce slightly faster and more readable code. Although its debatable on improved readability, i was surprised, and a tad dismayed, that the former is almost 50% faster than the latter.
This is because ifTrue:ifFalse: messages doesn't actually send the #ifTrue:ifFalse: message. To prove this, go delete all the ifTrue:ifFalse: messages in your base system. Everything still works. Take a look a the bytecodes for each:
| isNil ifTrue:ifFalse: | ifNil: |
1 <00> push inst 0 2 |
1 <00> push inst 0 2 <44> push self 3 |
Comments
Also to:do
[Ian Bicking] August 13, 2004 15:11:17.727
In Squeak at least this was also true for to:do: (and maybe to:by:do:). I think the reason was that they used this method a lot in graphic, so it (like ifTrue:ifFalse:) had to be really fast. It confused the heck out of me; I was playing around with Point, and tried to make to:do: iterate over all coordinates in the rectangle formed by the two points, but to:do: is hardcoded something like:
So to:do: with coordinates would always end up iterating over the diagonal (1@1 + 1 = 2@2).
Smalltalk's booleans are very much like the Lambda Calculus, but in the end that's just not fast enough, so really they only look like the Lambda Calculus.
I vaguely remember that in Squeak ifNil: was a primitive in the same way ifFalse:ifTrue: is...?
Re: ifTrue:ifFalse: Faster than ifNil:
[ Troy Brumley] August 13, 2004 15:15:30.417
Comment on ifTrue:ifFalse: Faster than ifNil: by Troy Brumley
Uhm, premature optimization is the root of all evil. Write it readable, and then profile :)
[Vassili] August 13, 2004 16:50:26.866
ifNil: and its ilk are not macroexpanded in VisualWorks. You can see an example of a macroexpanded ifNil: implementation for VW in my compiler article, but when actually adding ifNil: to VW we decided the speedup was not worth the added complexity. If speed matters, don't use it--but in most cases it doesn't.
To see what messages are macroexpanded, print or inspect "MessageNode.MacroSelectors". In Squeak, the equivalent is "MessageNode classPool at: #MacroSelectors". The implementations are not indentical, but you can see they came from the same source.
[Boris] August 18, 2004 18:45:49.085
Try loading OptimizeIfNil from Public Repository and recompiling your methods. Beware of downsides of sending neither #isNil nor #ifTrue:ifFalse: though :)