[squeak-dev] Object>>is:

Igor Stasenko siguctua at gmail.com
Fri Feb 11 14:19:13 UTC 2011


On 11 February 2011 15:06, Levente Uzonyi <leves at elte.hu> wrote:
> On Thu, 10 Feb 2011, David T. Lewis wrote:
>
>> On Fri, Feb 11, 2011 at 02:51:26AM +0100, Levente Uzonyi wrote:
>>>
>>> On Fri, 11 Feb 2011, Igor Stasenko wrote:
>>>
>>>> On 11 February 2011 02:28, David T. Lewis <lewis at mail.msen.com> wrote:
>>>>>
>>>>> We had a good deal of discussion earlier about adding Object>>is:
>>>>> with an inconclusive outcome:
>>>>>
>>>>> ?http://lists.squeakfoundation.org/pipermail/squeak-dev/2010-April/148501.html
>>>>>
>>>>> Igor's original proposal is:
>>>>>
>>>>> ?http://lists.squeakfoundation.org/pipermail/squeak-dev/2009-June/136793.html
>>>>>
>>>>> I have been tinkering around with Juan's SimpleMorphic in hopes of
>>>>> getting it running in Squeak alongside MVC and Morphic, and it would
>>>>> be convenient to have the default implementation of #is: in the image
>>>>> so I don't have to put it in a package override.
>>>>>
>>>>
>>>> Just yesterday i had  discussion about this with people in the lab. I
>>>> can't say that i heard something new regarding this,
>>>> and not saying that i'd like to resurrect the discussion.
>>>> So, in short: there was no objection concerning getting rid of isXXX
>>>> in favor of using #is: method.
>>>
>>> What about performance?
>>
>> I do not think that Juan would have chosen to use the #is: idiom for
>> his Cuis Morphic implementation if he thought that performance would
>> be a problem. It seems to work well.
>
> You're right, it's pretty fast, but methods that return only a boolean and
> have no arguments are special methods, which is true for almost every #is*
> methods. I did a quick benchmark to see the effects of the change:
>
> Object
>        compile: 'is: aSymbol
>
>                ^false'
>        classified: 'testing'.
> Morph
>        compile: 'is: aSymbol
>
>                ^aSymbol == #Morph or: [ super is: aSymbol ]'
>        classified: 'testing'.
> {
>        [
>                Smalltalk garbageCollect.
>                (1 to: 5) collect: [ :run |
>                        [ SystemNavigation default allObjectsDo: [ :each | ]
> ] timeToRun ] ].
>        [
>                Smalltalk garbageCollect.
>                (1 to: 5) collect: [ :run |
>                        [ SystemNavigation default allObjectsDo: [ :each |
> each isMorph ] ] timeToRun ] ].
>        [
>                Smalltalk garbageCollect.
>                (1 to: 5) collect: [ :run |
>                        [ SystemNavigation default allObjectsDo: [ :each |
> each is: #Morph ] ] timeToRun ] ] }
>        collect: [ :each | each value ].
>
> With SqueakVM (4.0.3 windows VM), I got the following results:
>  #(#(43 44 45 44 44) #(53 53 54 53 54) #(64 64 64 64 64)).
> So using #is: #Morph instead of #isMorph is 2.13x slower in this case.
>
> With CogVM (r2361 on windows), I got these (after a few runs that ensure
> that Cog compiles the code to machine code):
>  #(#(16 17 16 16 16) #(20 14 27 19 20) #(27 20 21 20 20))
> So using #is: #Morph instead of #isMorph is 1.42x slower in this case.
>
> I calculated the speedup with the following method (replace the array to the
> other case's to get the other result):
>
> #(#(16 17 16 16 16) #(20 14 27 19 20) #(27 20 21 20 20))in: [ :results |
>        (results third average - results first average / (results second
> average - results first average)) asFloat ].
>
> The difference for Cog is not significant, maybe just noise, but it's clear
> that using #is: is slower with SqueakVM.
>
> Let's see a bit larger scale benchmark: SmalltalkImage >>
> #cleanUpUndoCommands. Note that this method is a "heavy user" of #is*.
>
> (1 to: 5) collect: [ :run |
>        Smalltalk garbageCollect.
>        [ Smalltalk cleanUpUndoCommands ] timeToRun ].
>
> With SqueakVM:
> #isMorph : #(68 68 69 68 68)
> #is: #Morph : #(83 83 90 82 83)
>
> The difference is still there, but obviously smaller.
>
> With CogVM (I couldn't force it to compile the method to machine code):
> #isMorph : #(101 101 103 103 103)
> #is: #Morph : #(103 102 103 103 104)
>
> No real difference.
>
> So code that uses #is* methods in tight loops may be slower with SqueakVM,
> but probably won't with CogVM. The change probably won't have measurable
> effect on other code.
>
>>
>>>
>>>> The only thing which still looks controversial is too simple default
>>>> implementation which answers false.
>>>>
>>>> To my current opinion, Juan's variant is preferable. :) Yes. it should
>>>> answer false and don't contain any extra logic , like trying to follow
>>>> class hierarchy etc.
>>
>> My intention is to include the method copied directly from Cuis, which is:
>>
>> is: aSymbol
>>        "A means for cleanly replacing all isXXX like methods.
>>        Please use judiciously!
>>        Suggested by Igor Stasenko at
>>
>>  http://lists.squeakfoundation.org/pipermail/squeak-dev/2009-June/136793.html"
>>
>>        ^false
>
> Okay.
>
>>
>>>> Because it serves to replace isXXXX pattern, and not adding something
>>>> new (i.e. more 'userful'). So, answering false for Object class fits
>>>> well for this purpose.
>>>>
>>>> And of course solution to that problem is simple:
>>>> - avoid writing code in style, which require isXXX tests and then
>>>> branching. Nicely written code should use message dispatch instead.
>>>> Too bad, we are not living in perfect world :)
>>>
>>> Is it better to flood superclasses with no-op extension methods?
>>>
>>
>> Absolutely no. But the proposal is from June 2009 and was supported
>> by Andreas, whose judgement I trust a lot. This is the first time in
>> over 10 years of squeaking that I have ever suggested adding a method
>> to Object, so it's really not too much of a flood. And I promise
>> never to do it again ;-)
>
> The flooding is unrelated to #is:. It would be the side effect of Igor's
> suggestion: "- avoid writing code in style, which require isXXX tests and
> then branching.".
> Let's see the above example: SmalltalkImage >> #cleanUpUndoCommands. It
> sends #isMorph to all objects and then does something if the result is true.
> How could it be modified to satisfy Igor's suggestion?
> Implement Object >> #cleanUpUndoCommands which does nothing (this is the
> bloat) and implement Morph >> #cleanUpUndoCommands which does the real work.
> Then send this method from SmalltalkImage's method to all objects. No
> branching on the result of a #is* method, but an extra method for Object.
> Why is this worse than using #isMorph? Because this method is hardly useful
> from any other code, but #isMorph is.
>

Since this method is hardly useful from any other code but morphic,
then what it does in SmalltalkImage?
It should belong to UI universe.. and UI uninverse should know how to
tell all morphs to do that cleanup.. and then you don't need anything
related to it in Object protocol.
It makes no sense asking every object in system in a way like that.

So, all you need is to think a bit more broadly in a sense, how to
improve system and remove crappy patterns from use,
but not blindly replace one pattern by another , which replacing one
flood with another.


>
> Levente
>
>>
>> Dave
>>
>>
>>
>
>



-- 
Best regards,
Igor Stasenko AKA sig.



More information about the Squeak-dev mailing list