Am 19.09.2023 15:03:42 schrieb Thiede, Christoph <christoph.thiede@student.hpi.uni-potsdam.de>:
Hm ... ifTrue:ifFalse: sends are inlined whereas ifEmpty:ifNotEmpty: receives regular block closures, right? By the way, it's 5 % GC time for me only.
Monitoring BlockClosure allSubInstances size reveals that there are being created significantly more blocks in the image while running
[ [ [ #() ifEmpty: ['hallo'] ifNotEmpty: ['squeak'] ] repeat ] valueWithin: 10 seconds onTimeout: [] ] forkAt: 30.
Turns out that Object>>#value is faster (though less idiomatic):
[ #() ifEmpty: ['hallo'] ifNotEmpty: ['squeak'] ] bench '21,000,000 per second. 47.7 nanoseconds per run. 4.999 % GC time.'[ #() ifEmpty: 'hallo' ifNotEmpty: 'squeak' ] bench '43,400,000 per second. 23.1 nanoseconds per run. 0 % GC time.'[ #() isEmpty ifTrue: ['hallo'] ifFalse: ['squeak'] ] bench '52,900,000 per second. 18.9 nanoseconds per run. 0 % GC time.'
pushFullClosure: seems to create block instances eagerly (as opposed to Context instances).
Could a clever bytecode optimization share BlockClosure instances with the same/empty set of enclosed variables?
For now, just do it ourselves:
a := ['hallo'].b := ['squeak'].[#() ifEmpty: a ifNotEmpty: b ] bench '31,000,000 per second. 32.2 nanoseconds per run. 0 % GC time.'
Best,Christoph
Von: Marcel Taeumel via Squeak-dev <squeak-dev@lists.squeakfoundation.org>
Gesendet: Dienstag, 19. September 2023 13:14:05
An: gettimothy via Squeak-dev
Cc: Taeumel, Marcel
Betreff: [squeak-dev] Noticeable GC load for ifEmpty:ifNotEmpty:?Hi all --
[ #() isEmpty ifTrue: ['hallo'] ifFalse: ['squeak'] ] bench'127,000,000 per second. 7.85 nanoseconds per run. 0 % GC time.'[ #() ifEmpty: ['hallo'] ifNotEmpty: ['squeak'] ] bench7,580,000 per second. 132 nanoseconds per run. 78.0088 % GC time.'
Why is that? :-) Why is there an extra GC?
Here is the current implementation of #ifEmpty:ifNotEmpty:
ifEmpty: emptyBlock ifNotEmpty: notEmptyBlock
self isEmpty ifTrue: [^ emptyBlock value].
^ notEmptyBlock cull: self
Best,Marcel