-
-
Notifications
You must be signed in to change notification settings - Fork 33.6k
Description
Bug report
Bug description:
I suspect there might be a bug in the garbage collector under free threading. If I run this script
import gc
import threading
import time
def worker():
while not stop.is_set():
_ = [dict(x=i) for i in range(1000)]
stop = threading.Event()
threads = [threading.Thread(target=worker) for _ in range(8)]
for t in threads:
t.start()
time.sleep(2)
stop.set()
for t in threads:
t.join()
gen0 = gc.get_count()[0]
print(f"gen0 = {gen0}")
assert gen0 >= 0the assertion fails.
We observe in our full application that gen0 is quite negative, less than -10000 at times. The net effect of this is that garbage collection runs less frequently than it otherwise might, resulting in large GC pauses in our application (~3s). This doesn't seem to result in any functional problems aside from much longer stop-the-world pauses than ideal.
This seems to repro even if I set PYTHON_GIL=1 but not against an older version of python (3.10.12). I'm thus not completely sure if this is intended or not. It seems semantically ok for gen0 to go negative, like if deallocations exceed allocations that doesn't seem wrong, but is it supposed to?
I have reproduced this with 3.14t and cpython built against main.
CPython versions tested on:
3.14
Operating systems tested on:
Linux