[gclist] Finalizer flame wars.

Charles Fiterman cef@geode.geodesic.com
Fri, 10 May 1996 13:35:23 -0500


> 
> It seems to me that the finalizer flame war comes from a lack of
> understanding/agreement of what is being implemented upon what
> existing platform.
> 
>    The computer is a finite window with some strict a priori bound
> (=available physical electronic/magnetic memory) that gives a view
> upon a mathematically well-defined infinite Universe of objects,
> some of which are I/O monads that interact with the Outside World,
> and whose semantics is the root of all interest in the system.
> Most languages hide the fact that there be monads,
> or (worse even) give a low-level interface to the Universe;
> good languages don't (e.g. Clean).
>    Maybe the fact that the window is finite is unclean, low-level, etc,
> but if anyone knows any trick to escape this fact, please tell me.
> Until someones does tell me, I'll admit that we have to do with it.
>    Finalizers are primarily meant to free resources that are managed
> outside of the scope of the explored Universe, in the (Outside) Meta-World.
> Their implementation should indeed NOT interfere with the semantics
> of the explored Universe (unless and in so far as the Universe is reflective);
> however, they SHOULD interfere with the semantics
> of the Meta-World, by freeing idle resources from the finite pool.

Where is this true in the real world?? For example suppose finalizers
are used to free file handles. If the process is slow enough your program
will crash when it can't get a file handle. You will have an intrmittent
bug, it will doubtless occur on a users system at the maxamally inconvienient
time (when he has lots of data) and be impossable to reproduce. This is
precisely what we want to avoid. I never want to hear "Is there a programmer
aboard the aircraft? I'm getting the message open failed due to insufficient
file handles. Open of what? I'm not trying to open anything I'm trying to
land the ... OH SHIT!!"
 
Garbage collection should a tool suitable for mission critical programming.
Mission critical means "If it fails something unacceptable happens like an
aircraft becoming a post hole digger." Clearly collector based finalizers are
not useful in this context. So as a language designer I will do finalizers
in some other way. Having them lay around the garbage collector then becomes
a waste of time, a source of unnessisary complexity and an invitation to
disaster. Collector delays are a source of trouble already, collector based
finalizers make it worse even if they are an unused feature.

Languages need to be as simple as possable but no more so. Finalizers of
some kind are a requirment of mission critical programming. Collector based
finalizers are not up to the job. What seems to be up to the job is a directed
acyclic graph of finalizer objects kept on top of the object system and
open to user control. After building such a structure having others around
is simply a design error. PL/1 is the example of how to do it wrong by
having so many features no one can acceptably debug the language and
few users can acceptably learn it.

> >> Collectors need to be efficient and transparent.
> >
> > Efficient, yes!
> > Transparent, not necessarily!

I don't see a way to violate collector transparency without inviting
bugs. There can be minor exceptions to this like adjusting the collect
or expand heuristic or having the language note leaf objects and tell
the collector about them. But if the user can replace the mark function
there will be loose pointer bugs when he gets it wrong.

> Efficiency and Transparency are opposite requirements;

Almost agreed. But when listing priorities correctness is above the line.
This is not true of academic programming but it is true where I live.

Let us suppose you have a dozen variables used to tweak collector performance.
99% (*1) of programmers will tweak zero of them. The collector will be 
constantly checking them for programmer inserted values. The result is wasted 
time in almost all programs and small gains in the rest. Futher having these 
variables complicates your test plan. You have to test for all the meaningful
combinations of user switches or risk shipping an incorrect collector. This
is really poor design. Even throwing switches to get collector statistics
to a log file can be more dangerous than it looks. Those file writes can
trigger storage allocations at bad times.


*1 98.735% of all statistics are made up on the spot.