Ah, yes. push-full-closure. That needs to be garbage collected. That idea with sharing instances of FullBlockClosure is interesting ... not sure about long-running blocks though and re-entrancy... :-)
By the way, it's 5 % GC time for me only.
This depends on the current size of your object memory (or old space) and probably about the current load of the GC's internal data structures :-) I was just worried bout that "zero vs. not zero" observation.
Best, Marcel 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'] ] bench 7,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