[Vm-dev] An idea about better finalization support

Igor Stasenko siguctua at gmail.com
Thu Apr 23 06:47:23 UTC 2009


2009/4/23 Andreas Raab <andreas.raab at gmx.de>:
>
> This is actually quite similar to what I thought about for a more robust
> finalization solution. My thought was that you could just use linked lists
> (which have operations that are already supported by the VM for process
> management) and then make a weak subclass of Link that holds the object to
> be watched plus the finalizer for the object. When the VM traces such a link
> it puts it onto a VM-level finalization list and signals the finalization
> semaphore. The finalization process then pulls the entries from the list and
> calls the finalize method on it.
>

Yes, quite similar. I thought about using a globally registered list
(in special objects table), where VM could stockpile all weak refs
pending for finalization.
But then i thought, that decentralized version of it can be even
better - a developers could organize own list(s) and free choose own
criteria, like at which point they need to visit own list(s) and flush
them.

> Cheers,
>  - Andreas
>
> Igor Stasenko wrote:
>>
>>  In recent topic on Seaside list, someone has asked, why Seasider's
>> abandon the idea of using weak references (and use finalization
>> technique when they die).
>> The main issue was the slowness of weak finalization process
>> implemented in Squeak.
>>
>> The problem:
>> - sometimes developer needs to get a notification from system when
>> particular object become garbage, so an additional processing could be
>> activated, called finalization.
>>
>> How things currently working:
>>
>> Squeak provides a default finalization scheme implemented by
>> WeakRegistry class, where one could register a pair of weak reference
>> and executor. Its connected with finalization process , which governed
>> by WeakArray class.
>>
>> Upon each GC, the finalization process awakes and sending
>> #finalizeValues to all objects, registered in FinalizationDependents
>> collection.
>> When a WeakRegistry receives this message, it iterates over own
>> WeakIdentityKeyDictionary instance to find a pairs, for which key
>> (weak ref) became nil, and sends #finalize to the value (executor).
>>
>> The problem with such approach, is a linear time consumption spent for
>> scanning all registered key>value pairs.
>> If you have thousands of objects registered in that way, while only
>> few of them could become garbage, the finalization process still will
>> spend a fair amount of time, trying to determine which ones became
>> garbage.
>>
>> To eliminate this waste, we need to implement a scheme in VM, which
>> can help us to reach only those objects which is died during current
>> GC cycle, leaving rest untouched.
>>
>> Here is what i'd like to propose:
>>
>> - add a special class
>>
>> Object weakSubclass: #WeakReferenceWithNotification
>>        instanceVariableNames: 'list next'
>>        classVariableNames: ''
>>        poolDictionaries: ''
>>        category: 'Collections-Weak'
>>
>> so, that VM can check this special kind of weak reference in
>> ObjectMemory>>finalizeReference: method.
>>
>> A 'list' ivar can point to any object, we only need to be sure it
>> having at least one slot to hold a list head:
>>
>> Object subclass: #FinalizationList
>>        instanceVariableNames: 'head'
>>        classVariableNames: ''
>>        poolDictionaries: ''
>>        category: 'Collections-Weak'
>>
>> now, all we need is to modify #finalizeReference: method, to do
>> following at the moment of storing nil pointer:
>>
>> " this is not actually the slang code, just to illustrate what it does "
>>
>> (oop class isKindOf: WeakReferenceWithNotification) ifTrue: [
>>  | list |
>>  list := oop at: ListSlotIndex.
>>  oop at: NextSlotIndex put: (list at: HeadSlotIndex).
>>  list at: HeadSlotIndex put: oop.
>> ].
>>
>>
>> What it does, it simply links given oop to the list.
>>
>> And as you may suppose, if we have initial state:
>> - list with head == nil
>> - multiple instances with WeakReferenceWithNotification , all pointing
>> to our list, and having a weak refs,
>>
>> then after GC, if some of the refs become nilled, in a list's head we
>> will have a list of weak references we need to finalize (or do
>> anything else we want to).
>>
>> Then a finalization process in case of WeakRegistry, don't needs to go
>> through all weak references which are registered in itself, instead it
>> could simply do:
>>
>> "suppose we use a subclass "
>> WeakReferenceWithNotification weakSubclass: #WeakReferenceWithExecutor
>>        instanceVariableNames: 'executor'
>>        classVariableNames: ''
>>        poolDictionaries: ''
>>        category: 'Collections-Weak'
>> ...
>>
>> ref := list head.
>> ref notNil whileTrue: [
>>   ref executor finalize.
>>   ref := ref next.
>> ].
>> list head: nil.
>>
>> P.S. Me hopes ;) , that i successfully shown that the actual changes
>> to VM is quite simple and minimal. But effects of such change could
>> have a major impact on a finalization scheme performance.
>>
>>
>



-- 
Best regards,
Igor Stasenko AKA sig.


More information about the Vm-dev mailing list