I have a Python function that consumes a large amount of memory. When the function finishes, I want to release the memory and return the freed pages to the operating system by calling malloc_trim(0).
However, the memory isn’t released immediately — it only gets freed after a generation 2 garbage collection.
My first approach
I tried calling:
gc.collect()
malloc_trim(0)
manually after the function returns.
This works, but the Python documentation warns that:
The effect of calling gc.collect() while the interpreter is already performing a collection is undefined.
So this approach could potentially cause undefined behavior, which makes it unsafe for production use.
My second approach
Instead, I tried waiting for a natural gen=2 collection to occur, and then calling malloc_trim.
I did this by registering a GC callback:
def gc_trim_callback(phase, info):
if phase == "stop" and info["generation"] == 2:
malloc_trim(0)
gc.callbacks.remove(gc_trim_callback)
gc.callbacks.append(gc_trim_callback)
This works correctly when a generation 2 collection actually occurs — the callback triggers and malloc_trim runs.
The problem
The issue is that sometimes, after the heavy function finishes, the process goes idle before any generation 2 collection happens.
If the user doesn’t perform any further actions, the process can stay idle for hours, days, or even months, holding onto the unused memory indefinitely. That’s not acceptable for my use case.
I’ve thought of two very bad solutions for triggering a generation 2 collection “naturally”:
Adjusting the GC threshold using gc.set_threshold() to make gen2 collections happen more frequently — but this feels hacky and can negatively impact performance.
Creating many artificial circular references after the function returns, then freeing them to trigger a gen2 collection — also very hacky and inefficient.
So, in short, I can't trigger a gen2 collection as it can cause invalid behaviour. I can make it happen by some manipulations, which i want to avoid doing. Can you think on a better solution then what i have?