GC is just like async, but sometimes worse

2020/08/19
gc, garbage-collection
The non-GCed code share similar contagious trait as async code. Best not rely on GC right now and always support the manual close API. Hope future compiler will take work off instead.

The contagious similarities between GC and async

Some may already start to feel the contagious similarities between GC and async.

If not, read this post first: What Color is Your Function?, and the quote from: Wikipedia

The need for explicit manual resource management (release/close) for non-GCed resources in an object oriented language becomes transitive to composition. That is: in a non-deterministic GC system, if a resource or a resource-like object requires manual resource management (release/close), and this object is used as "part of" another object, then the composed object will also become a resource-like object that itself requires manual resource management (release/close).

To be clear: just like async, once there's a non-GCed resource in your GCed resource manager, you gotta provide a way to call the manual release explicitly. But unfortunately you can't solve this on a lower level, like reduce an async API to Promise then handle that with callback, there's no way to get lower than GC, and in language like JS there's no GC API at all.

Destructor in GC world

JavaScript have no way to archive destructor-alike for now.

Java have some way to archive destructor-alike, but not good.

Go have some way to archive destructor-alike, but not good.

Common explanation for the lack of destructor/constructor in GC language is the delayed nature of GC may cause the resource release happen really late, or completely missed before program exit.

Which is true, most GC will try to provide fast async dereference check & free, that is:

Even in an imaginary fully GCed language, with current GC standard, when and how long the GC will hit is still a problem. Most of us will assume the data is recovered when the reference is dropped, but there's no guarantee. To limit the total memory/resource under a certain point only with GC is still hard to archive, especially when async/thread is added to the mix.

Don't rely on GC

Most GC language will suggest API code to provide a conventional close function as resource destructor.

On the other side, life without GC not that bad actually, most value is used only within the function scope and work the same as GCed code, the resource release is manual anyway. The only annoyance is some reference needed to be passed around as argument or return value for efficiency.

So maybe just don't rely on GC, take the benefits of convenience from GC, and keep the explicit close function in API when dealing with resources.

Sidetrack: all should be compiler's job

We should move more "repeated" work to the language compiler, after we make the compiler faster and simpler in concept. Compiler should use as much time as needed to analyse the code and optimize, but not waste time. Thus hopefully we may see compiler optimize code for hours, mark all potential problem, check all GC or non-GC leaks, and completely restructure the code to the actual optimized structure.

And the related talk: Discussion: Making Programming Language Parsers, etc