[Vm-dev] Re: Too many full GCs in Cog/Spur ... while just drawing GUI ...

Eliot Miranda eliot.miranda at gmail.com
Fri Apr 8 23:48:06 UTC 2016


On Fri, Apr 8, 2016 at 2:57 PM, Bert Freudenberg <bert at freudenbergs.de>
wrote:

>
> On 08.04.2016, at 20:00, Eliot Miranda <eliot.miranda at gmail.com> wrote:
>
>
> On Fri, Apr 8, 2016 at 9:29 AM, Levente Uzonyi <leves at caesar.elte.hu>
> wrote:
>
>> So I suggest we should use both changes if it has no negative side
>> effects. Eliot? :)
>>
>
> +1.  I had hoped that scavenging would be run automatically, but this
> won't happen with huge allocations.  For small allocations, when eden is
> full, the machine code new primitive will set the "needs scavenge" flag,
> when #handleFailingBasicNew: runs the scavenger will run, and so there is
> no need to do Smalltalk garbageCollectMost, because that has happened
> implicitly.  But for huge allocations I think the code doesn't set the
> scavenge flag, it merely fails the primitive.  But I need to check this.
>
> What do we prefer, having the machine code for new always set the "needs
> scavenge" flag if an allocation failed because there was no room, or have #handleFailingBasicNew:
> et al calls Smalltalk garbageCollectMost explicitly?
>
>
> IMHO there’s no advantage to rely on the image to do that. I’d prefer
> handling it in the VM.
>
> When I saw Bert's message above, denying that basicNew: ever fails, I
> immediately repeated Bert's experiment, /knowing/ that basicNew /does/
> fail.  But to my surprise my experiment revealed Bert's result, that
> basicNew does not appear to fail :-).
>
>
> Now that’s a relief ;)
>
> Of course the gotcher is that the backward branch in the loop over
> allocation checks for events, and runs the scavenger, so a simple loop
> never shows failures.  It's difficult to make it fail, but fail it will :-)
>
>
> Yeah. So more smaller allocations will not make it fail, but few bigger
> ones does.
>

Right.

When exactly is a full GC triggered in the current scheme?
>

When handleFailingBasicNew: fails to allocate.  Here's the code:

Behavior>>basicNew
"Primitive. Answer an instance of the receiver (which is a class) with no
indexable variables. Fail if the class is indexable. Essential. See Object
documentation whatIsAPrimitive.
If the primitive fails because space is low then the scavenger will run
before the method is activated.  Check that space was low and retry
via handleFailingBasicNew if so."

<primitive: 70 error: ec>
ec == #'insufficient object memory' ifTrue:
[^self handleFailingBasicNew].
self isVariable ifTrue: [^self basicNew: 0].
self primitiveFailed

handleFailingBasicNew
"handleFailingBasicNew gets sent after basicNew has failed and allowed
a scavenging garbage collection to occur.  The scavenging collection
will have happened as the VM is activating the (failing) basicNew.  If
handleFailingBasicNew fails then the scavenge failed to reclaim sufficient
space and a global garbage collection is required.  Retry after garbage
collecting and growing memory if necessary.

Primitive. Answer an instance of this class with the number of indexable
variables specified by the argument, sizeRequested.  Fail if this class is
not
indexable or if the argument is not a positive Integer, or if there is not
enough memory available. Essential. See Object documentation
whatIsAPrimitive."

<primitive: 70>
Smalltalk garbageCollect < 1048576 ifTrue:
[Smalltalk growMemoryByAtLeast: 1048576].
^self handleFailingFailingBasicNew "retry after global garbage collect"

handleFailingFailingBasicNew
"This basicNew gets sent after handleFailingBasicNew: has done a full
garbage collection and possibly grown memory.  If this basicNew fails
then the system really is low on space, so raise the OutOfMemory signal.

Primitive. Answer an instance of this class with the number of indexable
variables specified by the argument, sizeRequested.  Fail if this class is
not
indexable or if the argument is not a positive Integer, or if there is not
enough memory available. Essential. See Object documentation
whatIsAPrimitive."

<primitive: 70>
"space must be low"
OutOfMemory signal.
^self basicNew  "retry if user proceeds"

So if one does SomeClass basicNew and this fails with the error code
#'insufficient object memory' it did so because the VM is (at least
temporarily) out of memory.  If the primitive invoked by basicNew sets the
"scavengeNeeded" flag, then by the time we get to the "^self
handleFailingBasicNew" send in basicNew, the scavenger will have run,
because events are responded to when a method builds a frame, which
basicNew does as it fails.  So basicNew sends handleFailingBasicNew to
retry the allocation, assuming the scavenger has run.

So if handleFailingBasicNew fails it means there's not enough room in
newSpace or in oldSpace.  Therefore it runs Smalltalk garbageCollect to
reclaim space in oldSpace, and then invokes handleFailingFailingBasicNew to
retry the allocation a third time.  If handleFailingFailingBasicNew it
means we're really out of space and so it raises the OutOfMemory exception.

The code is similar for basicNew:.


> - Bert -
>
>
>
>
>


-- 
_,,,^..^,,,_
best, Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20160408/6cbbc252/attachment.htm


More information about the Vm-dev mailing list