[squeak-dev] Re: How weak finalization affects the performance

Igor Stasenko siguctua at gmail.com
Tue Oct 26 10:02:11 UTC 2010


On 26 October 2010 11:49, Andreas Raab <andreas.raab at gmx.de> wrote:
> Hi Igor -
>
> I'm having a hard time understanding how adding a delay would improve
> performance. In my code, adding delays generally does the opposite :-) Can
> you explain *why* you see a performance improvement? The work done for each
> finalized object doesn't differ, does it? So how come you see an
> improvement?
>

Finalization is triggered at each GC cycle. Putting 5 sec delay makes
a finalization process to
do weak containers scavenging not often than each 5 seconds,
instead after each GC.

The amount of work to do finalization is same, but you forgetting the cost
of scanning weak dicts to find the objects to be finalized.

The code above actually illustrating this overhead:

| dict b |
dict := WeakKeyDictionary new addAll: (( 1 to: 1000 ) collect: [:i |
i->i] ); yourself.
WeakArray addWeakDependent: dict.

Here, at each GC cycle, a 'dict finalizeValues' will be sent,
which leads to looping over 1000 entries.
Add dict with 10000 entries, and you will loop over 10000 after each GC.



> Cheers,
>  - Andreas
>
> On 10/26/2010 12:25 AM, Igor Stasenko wrote:
>>
>> Here the idea, which came to Chris,
>> put a delay into #finalizationProcess loop:
>>
>> finalizationProcess
>>        [true] whileTrue:
>>                [ WeakFinalizationList initTestPair.
>>                FinalizationSemaphore wait.
>>                FinalizationLock critical:
>>                        [
>>                        WeakFinalizationList checkTestPair.
>>                        FinalizationDependents do:
>>                                [:weakDependent |
>>                                weakDependent ifNotNil:
>>                                        [weakDependent finalizeValues]]]
>>                        ifError:
>>                        [:msg :rcvr | rcvr error: msg].
>>                5 seconds asDelay wait.
>>                ].
>>
>>
>> And here a simple benchmark, which triggers GC often:
>>
>> [ Array new: 100 ] bench
>>
>> without delay:
>>
>> '2,450,000 per second.'
>> '2,490,000 per second.'
>> '2,490,000 per second.'
>> '2,480,000 per second.'
>> '2,530,000 per second.'
>>
>> with delay:
>>
>> '2,670,000 per second.'
>> '2,680,000 per second.'
>> '2,690,000 per second.'
>> '2,730,000 per second.'
>>
>> roughly about ~8% faster :)
>>
>> But now lets put something big into weak array:
>>
>> | dict b |
>> dict := WeakKeyDictionary new addAll: (( 1 to: 1000 ) collect: [:i |
>> i->i] ); yourself.
>> WeakArray addWeakDependent: dict.
>> b := [ Array new: 100 ] bench.
>> WeakArray removeWeakDependent: dict.
>> b
>>
>> without delay:
>>
>> '1,840,000 per second.'
>> '2,060,000 per second.'
>> '2,130,000 per second.'
>>
>> with delay:
>>
>> '3,030,000 per second.'
>> '2,880,000 per second.'
>> '2,890,000 per second.'
>>
>> Do not forget to do:
>> WeakArray restartFinalizationProcess
>>
>> when you changing the #finalizationProcess method,
>> otherwise you won't see real numbers.
>>
>> So, i like the idea of putting delay there.
>> Finalization is eventual, and there is no hard guarantees that it will
>> happen in micro-second just after some object become garbage.
>> So, be it 5 seconds or 1000 seconds not really matters.
>> What is matters that with delay we win much more, by avoiding wasting
>> time in finalization process too often.
>>
>>
>
>
>



-- 
Best regards,
Igor Stasenko AKA sig.



More information about the Squeak-dev mailing list