Does calling `gc()` manually, result in all `finalizers` being executed immediately?
Asked Answered
G

1

7

I have some code that I suspect is leaking memory. As the code uses ccall and maintains significant information held inside pointers, which are supposed to be free'd by code that is ccalled during finalizers.

In my debugging I am calling gc(). And I want to know if this will immediately trigger all finalizers that are attached to the objects that have moved out of scope

Answers should be concerned only with julie 0.5+.

Gulf answered 10/6, 2017 at 2:57 Comment(0)
G
8

After the discussion on @Isaiah's answer (deleted), I decided to poke some internals folks and get some clarity on this. As a result, I have it on good authority that when gc() is called at the top level – i.e. not in a local scope – then the following assurance can be relied upon:

if an object is unreachable and you call gc() it’ll be finalized

which is pretty clear cut. The top-level part is significant since when you call gc() in a local scope, local references may or may not be considered reachable, even if they will never be used again.

This assurance does sweep some uncertainty under the carpet of "reachability" since it may not be obvious whether an object is reachable or not because the language runtime may keep references to some objects for various reasons. These reasons should be exhaustively documented, but currently they are not. A couple of notable cases where the runtime holds onto objects are:

  • The unique instance of a singleton type is permanent and will never be collected or finalized;

  • Method caches are also permanent, which in particular, means that modules are not freed when you might otherwise expect them to be since method caches keep references to the modules in which they are defined.

Under "normal circumstances" however – which is what I suspect this question is getting at – yes, calling gc() when an object is no longer reachable will cause it to be collected and finalized "immediately", i.e. before the gc() call returns.

Gelb answered 12/6, 2017 at 15:19 Comment(2)
That's a great answer Stefan. Would it be fair to say that this is true only of the current gc() implementation, and is not a language contract? i.e, this behaviour can change in the future. For example, if and when we get a multi-threaded gc?Accursed
Yes, if we get a concurrent gc, all bets are off – but we will have to consider the impact of that, of course. In a concurrent gc, there are mutator threads and collector threads which run at the same time, so it's not entirely clear what it even means to call gc() in a mutator thread. It could potentially be arranged to block the mutator thread in which it is called until a "full collection" has occurred in the collector threads. Or it could invoke a stop-the-world gc algorithm in place of the concurrent collector, but then we have two different gc implementations, which would be odd.Gelb

© 2022 - 2024 — McMap. All rights reserved.