We recently tried tweaking the GC threshold values in our FastAPI server running Python 3.11.5 from the default of (700, 10, 10) to incredibly high values of (100_000, 500_000, 1_000_000). From the screenshot below showing generation 2 GC event logs in reverse chronological order, you can see that the only time we logged a non-zero collected
value was when I manually ran gc.collect()
(generation
kwarg defaults to 2) in the main event loop (using a live aiomonitor console session).
All the other logs before and after this show zero collected objects. What’s more peculiar is that they occur almost periodically at 3-4 minute intervals.
Why are the generation 2 GC events occurring so frequently and reporting zero collected objects consistently?
Here’s the code for the log callback function we appended to gc.callbacks
:
def log_gc_lifecycle_event(phase: str, info: dict):
nonlocal gc_start_time
now = time.monotonic()
if info['generation'] != 2:
# We only care about gen 2 collections.
return
info_to_log = {
'gc_phase': phase,
'generation': info['generation'],
}
if phase == 'start':
# Retain pre-GC figures.
gc_start_time = now
if phase == 'stop':
duration = now - gc_start_time
info_to_log.update(
{
'duration': duration,
'collected': info['collected'],
'uncollectable': info['uncollectable'],
'generation_2_object_count': len(gc.get_objects(2)),
}
)
gc_start_time = None
gc_logger.info(f'Garbage collection event: {phase}', **info_to_log)