[squeak-dev] The Inbox: Tools-LM.828.mcz

Florin Mateoc florin.mateoc at gmail.com
Wed Aug 15 03:48:17 UTC 2018


Hi Eliot,

On 8/14/2018 12:49 PM, Eliot Miranda wrote:
> Hi Florin,
>
>> On Aug 14, 2018, at 8:03 AM, Florin Mateoc <florin.mateoc at gmail.com> wrote:
>>
>>> On 8/14/2018 4:52 AM, Leon Matthes wrote:
...
>>> I would also appreciate feedback on this small piece of code:
>>>    + PointerFinder on: self object except: {self}, ObjectExplorerWrapper
>>> allInstances! 
>>>    - self flag: #tooMany. "mt: Note that we might want to ignore references
>>> caused by this tool." 
>>>    - self object chasePointers.! 
>>> I really don't like the use of allInstances in this case, but I didn' see a
>>> better way to find the ObjectExplorerWrappers that might hog references to
>>> the Object in question.
>>
>> Why don't you like the use of allInstances in this case? finding all references belongs to the same kind of meta
>> programming activities as finding all instances, so if there is a case where allInstances should be used, it is exactly
>> something like this
> The point is that the garbage collector is not eager.  A reference counting GC can be eager, except in the collection of cycles.  Practical implementations almost always include some form of deferment, such as Peter Deutsch’s Deferred Reference Counting, which defers counting the stack until a fixed sized zero count table has filled up.  So in practice garbage collectors do not collect all garbage immediately.  But allInstances indiscriminately trawls the heap, potentially reviving otherwise inaccessible objects that are yet to be collected.  In this case these objects can’t possibly prevent GC, so they’re spurious.  In this case it does no harm (a false positive of something that should be excluded has no effect on the pointer search).  But it’s still potentially go gust by and, as I said, slower to compute than traversing my the scene graph.
>
> This last point is important.  With 64-bits we can have apps with huge heaps and a PointerFinder may be a very important tool in fixing storage leaks within them.  Even more important then that time not be wasted using a catch all like allInstances to kick off a search. 


I was too succinct in my comment, thus inexact. Of course, both allInstances and allReferences closely interact with the
garbage collector.

E.g. in VisualAge, the implementation of allInstances is actually not a primitive but:

allInstances
    "Answer an indexable collection containing all the instances of the
     receiver."

    "There might not be any, so check for that case first."
    self basicAllInstances isEmpty  ifTrue: [ ^ #()].

    "Since there are instances, clean house and ask a second time."
    self methodDictionary notNil ifTrue: [
        "Let go of any classes and method dictionaries being kept in vm caches."
        self methodDictionary flushCache].
    System globalGarbageCollect.
    ^ self basicAllInstances


And very similarly, the implementation of allReferences is:

allReferences
    "Answer an indexable collection containing all the objects which
     reference the receiver."

    self basicAllReferences isEmpty  ifTrue: [ ^ #()].
    System globalGarbageCollect.
    ^ self basicAllReferences


Where basicAllInstances and basicAllReferences are the actual primitives.

When chasing memory leaks, you have to have an understanding of what can possibly hold onto the objects that you are
looking for, including the very tools that you are using as you are looking for references, possibly open inspectors,
debuggers, closures in methods invoked, etc. Of course, the snippet shown above is only a crude approximation of that,
but I don't think that the usage of allInstances in itself is a problem.

Presumably when you start chasing a memory leak, the leak is real and something other than object explorers are holding
onto the object, and those other references are more relevant to your search, but, as Bob said, it is easy to shoot
yourself in the foot if you forget about your exclusions


>> Regarding the previous issues discussed, I agree that #ifTrue: is not obvious. More than that, I have seen many bugs
>> caused by people not realizing that it would sometimes return nil, even if the block would always return something
>> notNil. So I would argue against brevity in this instance, I think
>>
>>     e ifTrue: [s] ifFalse: []
>>
>> would avoid these kinds of errors, so I would prefer it.
> This one is more debatable, but I find it troublesome that someone would not know what the default return is.  It could be self, it could be nil, but that there is a definition is important, and it should be known.  So for me I always go for the short form.
>
>  I think that the implementation of control structure via closures and messages is a) a core part of the system design, implying extensible control structures, deeply elegant and informed by computability theory, b) foundational to the system, both in the system being built upon these control structures, and in their definition being included in the system, and, with sufficient effort, actually extensible (see Marcus Denker’s magnificent mustBeBooleanMagic: in Pharo), b) beautifully concise; one can read the entirety of Boolean, True and False in a few minutes and the insight it gives into system design is enormous.  I still remember the thrill of getting it for the first time.  A teacher of Smalltalk should strive to give their students that same thrill.  This is one of the most profound and beautiful parts of the system and of computing.  The curly bracket languages are so weak in good part because they don’t embody this.
>

I tend to view

    e ifTrue: [s]

as merely syntactic sugar for

    e ifTrue: [s] ifFalse: []

and I am not a fan of syntactic sugar - these expressions are perfectly equivalent, with no chance of them ever being
extended to mean something different - especially when the syntactic sugar form is error-prone.

They feel more like allowing braces to be omitted in curly bracket languages when there's a single statement in the
branch - sure, the end result is more concise, and the developers should really learn their control structures, but the
additional errors being introduced as a result make it not worth it IMHO




More information about the Squeak-dev mailing list