Garbage collection for the over attached.

In the late 1950s, a computer scientist named John McCarthy, while designing the programming language Lisp, ran into a problem that nobody had thought to solve before, because nobody had built a programming language that produced the problem in the first place.

The problem was this. Lisp programs, more than the programs of any previous language, allocated lots of small objects, used them briefly, and then moved on. Each new object took up a little memory. The computer, which had a finite amount of memory available, would, given enough time, run out of room, even though most of the objects it had allocated were no longer being used for anything. The objects were, in the technical sense, still there, still occupying space, still recorded in the system's bookkeeping, but no part of the running program was paying any attention to them. They were not being read. They were not being written. They were not being referenced by any active piece of code. They were simply taking up room.

McCarthy's solution, which is now in some form a part of almost every modern programming language, was an automated routine called the garbage collector. The garbage collector, periodically, walked through the system's memory, identified the objects that no active code still referenced, and reclaimed the space they had been occupying, returning it to the system for new allocations. The program continued running. The memory it could use was, after each collection, larger than it had been before. The collected objects, having been determined to be no longer in use, ceased to exist.

I want to write about this, in this chapter, because I have come to think the garbage collector is one of the most important pieces of engineering humans have ever built, and because the principle behind it is one of the most important pieces of self-knowledge a person can learn at any age. The principle is this. Some of what you are still carrying, you are no longer using. Some of what you are no longer using, you do not even know is there. The carrying of unused things has a cost. The cost is paid in working memory the rest of your life needs.

∗ ∗ ∗

Let me describe how garbage collection actually works, because the mechanism is illuminating in a way the metaphor alone is not.

Modern garbage collectors use various algorithms, but the most pedagogically clean one is called mark and sweep. The collector begins by identifying a set of roots: pieces of memory that are unambiguously still in use, because the running program is currently pointing at them. From the roots, the collector traces every reference. Anything reachable, by any chain of references starting from a root, is marked as live. Anything not reachable, after the entire trace has completed, is, by definition, garbage. The collector then sweeps through memory and reclaims everything that was not marked.

The key word in this entire description is reachable. An object is live not because it once meant something, not because it was once allocated for a reason, not because some part of the program once cared about it, but because, at the moment of the collection, some chain of references actually leads to it from the active state of the program. Unreachable objects may be elaborate. They may have been important. They may have, in some earlier era of the program's life, been at the center of everything. None of this matters at the moment of collection. The only question the collector asks is: is any currently running part of the program pointing at this object? If yes, the object survives. If no, the object is freed.

This is, I want to suggest, the cleanest model I have ever encountered for thinking about what a healthy adult mind ought, periodically, to do with the contents of its own memory.

roots unreachable today people I love work in hand tonight's plans my sister's call the dog years the next chapter a quarrel from 2014 an old grudge, unrelevant the ledger somebody kept a self I no longer am a comment from 1993 live: reachable from a root garbage: nothing alive points here

Figure 20.1   The reachable objects, on the left and middle, are connected to today by chains of references. The unreachable objects, on the right, are still there, still taking up room, but no part of the living self is currently pointing at them.

∗ ∗ ∗

I want to be very careful in this next part of the chapter, because the analogy can be misapplied in ways that have caused real damage in the popular literature on self-help, and I would like to do no such damage.

The cheap version of this argument goes let go of everything that no longer serves you. The cheap version has been on a thousand posters, and the cheap version is wrong, because it conflates two things that the engineering distinction is precisely designed to keep apart. The two things are unreachable and painful. They are not the same thing. An object can be unreachable and painless, in which case its collection costs nothing and frees memory. An object can be reachable and painful, in which case its collection is not available to you, because some live part of you is still genuinely using it. The discipline of garbage collection is not to free everything that hurts. The discipline is to free what is no longer reachable, regardless of whether or not it currently hurts.

I want to apply the distinction to specific cases, because the abstract version is too easy to nod at and forget.

The grief I described in the interlude, about Koko and Knoppix, is, in the engineering sense, reachable. The relationships are over, but the love is not unreferenced. Live parts of me, every day, are still pointing at the dogs. The patience I learned from them is reachable from my present-tense behavior. The capacity to be in a room without performing presence is reachable from my current friendships. The compassion they trained in me is reachable from every interaction I have with another creature. The dogs themselves are dead. The structures the dogs built inside me are alive, and the references back to the dogs are part of the chain that keeps those structures live. To garbage-collect the grief, in this case, would be to break the references that allow the structures to be reached. The structures would, if the references were cut, drift into unreachability themselves. The cost of premature collection would be catastrophic, in the strict engineering sense. The collector, asked to evaluate this region of memory, correctly returns live.

This is true, I want to say, of any grief that is still doing work. The mother you lost as a child, the father you wished you had, the friendship that ended, the marriage that did not survive: if any current pattern in your life depends, in any chain of references, on what those relationships gave you, then the relationships are reachable, and the carrying of them is not garbage. The carrying is, in fact, the mechanism by which the value those relationships built is still available to you. To collect them prematurely is to lose the value along with the references.

Now the harder case.

I told you, in Chapter 8, about the man who kept a ledger. The man was my uncle. I told you, briefly, in the interlude, that he was alive when the worst of my own crises was happening, and that he died, along with my father, in the years since. I want to talk now, briefly, about what has happened to those two men in my own internal memory, because the answer is, I think, the cleanest example of garbage collection I can offer.

For most of my adult life, I carried, with respect to both men, a complicated package of feelings that I am going to describe with as little drama as possible. The package contained anger, which had been real, and disappointment, which had been real, and a kind of permanent low-level vigilance, which had been useful when I was eighteen and was less useful as I got older. The package also contained, embedded in it, the ledger itself. The specific accounting of what I had been given and what I had been denied. The unbalanced sums. The closing of the account when I was eighteen. The whole apparatus of who-owed-what-to-whom that the uncle, in his way, had taught me to keep.

For a long time, I assumed the package was reachable. I assumed that some live part of me was still using it. I would, periodically, consult it. I would tell the story of my childhood, to friends, to therapists, in some sense to myself, and the ledger would come up. The ledger felt, at the time of telling, alive. The ledger felt necessary.

I want to say plainly what I now believe, with the calm of several years of perspective. The ledger was, by the time I was thirty, already unreachable. No live part of me was using it for anything. The telling of it, to friends and therapists, was not a use of the ledger. It was a maintenance ritual that kept the ledger artificially marked as live. The maintenance was costly. The ledger occupied a region of working memory that the rest of my life needed for other things. The vigilance it required was the vigilance I would later discover was strangling my company, was wearing out my marriage, was preventing me from being present with people who were trying to love me.

When both men died, something happened that I did not expect, and that I want to describe without sentimentality. The active references to the ledger, in my present-tense life, began to thin. There was no longer anyone to be careful around. There was no longer a future encounter in which the ledger might need to be presented. The ledger was, in the strict engineering sense, becoming unreachable. I noticed, slowly, over months, that I could go for days without consulting it. Then for weeks. Then for entire months. The collector, working in the background, was doing its job. The ledger, eventually, was freed.

I want to be honest about something, because the chapter would be cowardly otherwise. The freeing did not feel like liberation. It did not feel like victory. It felt, mostly, like nothing. There was no triumphant moment of release. There was just, over time, a quiet absence. One Tuesday morning I noticed I had not thought about either man in three weeks, and that the not-thinking had cost nothing, and that the working memory that had been occupied by the ledger was now occupied by something else, which was, on inspection, the writing of this book. The ledger had been freed. The book had been allocated in the space that the ledger had been holding.

This is what garbage collection feels like when it works. It does not feel like anything. The space simply, quietly, becomes available, and the rest of the system, in the way systems do, expands to fill it.

∗ ∗ ∗

Here is a small piece of Python that implements mark-and-sweep on a toy heap, because seeing the algorithm written down makes the principle concrete.

def mark_and_sweep(heap, roots):
    """
    Perform one cycle of mark-and-sweep garbage collection.

    Inputs:
        heap:  a dict mapping object ids to objects, where each
               object has a 'refs' field listing the ids of other
               objects it references
        roots: a list of object ids that are unconditionally live

    Returns:
        a new heap containing only the reachable objects.
    """
    # MARK PHASE: trace every reference reachable from a root
    live = set()
    queue = list(roots)
    while queue:
        obj_id = queue.pop()
        if obj_id in live:
            continue
        live.add(obj_id)
        for ref in heap[obj_id]['refs']:
            if ref not in live:
                queue.append(ref)

    # SWEEP PHASE: remove anything not marked live
    return {obj_id: obj for obj_id, obj in heap.items() if obj_id in live}


# A toy interior heap of things-the-mind-is-carrying
heap = {
    'today':           {'value': 'present',        'refs': ['dog_years', 'work']},
    'dog_years':       {'value': 'patience',       'refs': ['compassion']},
    'compassion':      {'value': 'live',           'refs': []},
    'work':            {'value': 'in progress',    'refs': []},
    'quarrel_2014':    {'value': 'unresolved',     'refs': ['old_grudge']},
    'old_grudge':      {'value': 'inert',          'refs': []},
    'ledger':          {'value': 'archived',       'refs': []},
    'old_self':        {'value': 'a former mode',  'refs': []},
}

roots = ['today']

before = set(heap.keys())
after = set(mark_and_sweep(heap, roots).keys())

print(f"Before collection: {len(before)} objects")
print(f"After collection:  {len(after)} objects")
print(f"Freed:             {sorted(before - after)}")

The toy heap contains eight objects. The roots contain only one: today. The collector traces from today, finds dog_years by direct reference, finds compassion by indirect reference, and finds work. Four objects are reachable. The other four, including the quarrel from 2014, the old grudge, the ledger, and the old self, are not reachable from today. They are still in the heap. They are still occupying memory. The collector removes them. The heap, after collection, is half its previous size, and the remaining objects are exactly the ones the present-tense self is actively using.

I want to point out the structure that makes this work. The mark phase does not ask does this object hurt? It asks is this object reachable from a root? The decision is made by reference tracing, not by emotional valence. This is the entire engineering trick. An object that hurts but is reachable survives the collection, because something live is still pointing at it. An object that does not hurt but is not reachable is, nonetheless, collected. Pain and reachability are independent variables, and the collector takes no notice of one of them.

∗ ∗ ∗

I want to close the chapter with one quiet observation, because it is the chapter's most useful operational consequence.

The garbage collector cannot be called manually, in any reliable way. You cannot, by trying, free the unreachable things in your own head. The attempt to free them by force is, on inspection, itself a maintenance ritual that keeps them marked as live. The harder you try to let go of the old quarrel, the more references you create to it, the more reachable it remains. The trying is the carrying.

What the collector requires is not effort but neglect. The objects you no longer need become collectible when you simply stop visiting them. Not because you have resolved them. Not because you have forgiven them. Not because you have processed them. Because you have, gradually, stopped consulting them, and the references that were keeping them alive have, in the background, atrophied. The collector, working continuously and quietly, identifies the now-unreferenced objects and reclaims their space, while you are doing something else.

The discipline this chapter offers is the discipline of being patient with the collector. The collector is real. The collector is running. The collector does not need your help. The collector needs you to stop maintaining the references that you have been quietly maintaining without noticing. The maintenance has been the entire problem. Once the maintenance stops, the collection happens on its own, and you discover, in your fortieth year or your sixtieth, that an entire region of your mind that used to be occupied by an old grievance is now, somehow, occupied by a book, a friendship, a quiet morning, or whatever else needed the room.

This is, in some quiet way, what growing up is. It is the cessation of a maintenance ritual nobody told you you were performing, and the gradual reallocation of the memory that ritual had been costing, to the parts of your life that you would, given a fair choice, prefer to be doing.

∗ ∗ ∗

A small exercise

Find the maintenance.

Identify one piece of internal content you have been carrying for a long time that, on honest inspection, no current decision in your life requires you to be carrying. An old quarrel. A ledger somebody once kept. A self-image you have outgrown but still occasionally consult. A grudge against someone who no longer affects your life.

Now ask: what maintenance ritual am I performing that keeps this object marked as live? The ritual will, in most cases, be a habit of returning to the content. Telling the story of it. Rehearsing the argument. Consulting the ledger to confirm the score is still what it was. The maintenance is rarely loud. The maintenance is usually a small recurring visit, often almost reflexive, that the mind performs without noticing.

You do not have to stop the ritual today. You only have to notice it. Noticing the maintenance is the first step in letting it lapse. The lapse, over months, is what allows the collector to do its work. You are not, in this exercise, freeing anything by force. You are merely identifying the small recurring action that has, without your awareness, been keeping a useless object on the live list for years.

The freeing, when it comes, will not feel like an event. It will feel like a quiet absence. One ordinary morning, you will notice that the object has not been visited in some time, and that the space it occupied has, without your having done anything specifically, become available for something else.

Chapter 21 is the last chapter of the book proper, before the Epilogue. It is about the fact that there is no final, refactored version of the self, and that the work of self-modification is, on inspection, the work of a lifetime rather than a project with a deliverable. The chapter is named for the engineering practice of refactoring, which is the continuous improvement of code while preserving its behavior, and which is, on its best days, also a working description of what it means to be a thoughtful adult.

For now, the page closes here. The collector is real. The collector is running. The collector does not require your effort. The collector requires only that you stop visiting the objects you no longer need, and that you trust the long quiet work of unattended things becoming, in their own time, unreferenced, and unreferenced things becoming, in their own time, gone.

← Chapter 19                   Chapter 21 →