On Tue, 16 Nov 2010, Juan Vuletich wrote:
Hi Levente,
Levente Uzonyi wrote:
Hi,
I'm mostly ready with this cleanup, only a few methods left in the image that use #== for integer comparison. Some of them must use #==, others may be changed, but I wasn't sure if the code will work if it's changed or not. If you'd like to check these methods, then evaluate the following in a workspace:
... code here...
Cheers, Levente
Thanks for the snippet! It is now a method in Cuis. I also checked a bit on trunk. In all senders of #nextObject you can apply the pattern in #allObjectsDo:. Instead of assuming == 0 for last #nextObject, it assumes that Object new will go at the end. If that ever changed, a few places would need fixing...
I'm not sure if it's ok to use that pattern in ImageSegment. Even if it's ok, the code is so messy, that it seems to be hard to apply the pattern without breaking the code.
As an experiment, in #allObjectsDo: I tried to remove the Object new stuff and replace with '[ 0 = object and: [ object isMemberOf: SmallInteger ]] whileFalse: ', but my test became extremely slow. I suspect #= is sending the message even if it has its own bytecode... So, the only method that remains with the '0 ==' pattern in Cuis is #critical:ifLocked: , as I'm not sure if we can clean it.
#= is a special selector, so I'm sure it won't send a message if it doesn't have to. It's possible that #= is a bit slower than #== because it has to do some extra checks, but the difference is probably neglible. Here's a benchmark:
| offset equality identity | Smalltalk garbageCollect. offset := [ 1 to: 1000000 do: [ :i | ] ] timeToRun. equality := [ :x | [ 1 to: 1000000 do: [ :i | 0 = x ] ] timeToRun ]. identity := [ :x | [ 1 to: 1000000 do: [ :i | 0 == x ] ] timeToRun ]. { 0. 1. SmallInteger maxVal. SmallInteger maxVal + 1. nil. Object new. 0.0. Array new. 1/2 } collect: [ :each | each -> ({ equality value: each. identity value: each. equality value: each. identity value: each. equality value: each. identity value: each } - offset) ].
And my results on CogVM:
{ 0->#(3 2 3 1 3 2). 1->#(2 4 3 0 3 4). 1073741823->#(3 3 2 1 3 5). 1073741824->#(221 4 223 1 223 4). nil->#(14 4 14 0 15 4). an Object->#(14 5 13 1 14 4). 0.0->#(622 5 623 2 624 4). #()->#(16 5 14 1 16 4). (1/2)->#(260 4 259 1 258 5) }
So the cause of the slowdown in your #allObjectsDo: implementation is that #= is only fast if both the receiver and the argument are SmallIntegers, otherwise there will be message sends.
Another way to implement #allObjectsDo: without the marker object is to replace the loop condition with: object class == SmallInteger. It's actually the same as your implementation without the #= check. #isMemberOf: is optimized to non-real sends. This is as fast as the current implementation on my pc.
Levente
Cheers, Juan Vuletich