diff options
author | Mark Shannon <mark@hotpy.org> | 2024-03-20 08:54:42 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-20 08:54:42 (GMT) |
commit | 15309329b65a285cb7b3071f0f08ac964b61411b (patch) | |
tree | 83b5be564755d7ea396c76eda29e6d33faf535d9 /Lib/test/test_gc.py | |
parent | d5ebf8b71fd18d7a1f2f6b670a2c18749dc2b55e (diff) | |
download | cpython-15309329b65a285cb7b3071f0f08ac964b61411b.zip cpython-15309329b65a285cb7b3071f0f08ac964b61411b.tar.gz cpython-15309329b65a285cb7b3071f0f08ac964b61411b.tar.bz2 |
GH-108362: Incremental Cycle GC (GH-116206)
Diffstat (limited to 'Lib/test/test_gc.py')
-rw-r--r-- | Lib/test/test_gc.py | 72 |
1 files changed, 52 insertions, 20 deletions
diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py index f1a7afa..ce01916 100644 --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -384,19 +384,11 @@ class GCTests(unittest.TestCase): # each call to collect(N) x = [] gc.collect(0) - # x is now in gen 1 + # x is now in the old gen a, b, c = gc.get_count() - gc.collect(1) - # x is now in gen 2 - d, e, f = gc.get_count() - gc.collect(2) - # x is now in gen 3 - g, h, i = gc.get_count() - # We don't check a, d, g since their exact values depends on + # We don't check a since its exact values depends on # internal implementation details of the interpreter. self.assertEqual((b, c), (1, 0)) - self.assertEqual((e, f), (0, 1)) - self.assertEqual((h, i), (0, 0)) def test_trashcan(self): class Ouch: @@ -847,16 +839,6 @@ class GCTests(unittest.TestCase): self.assertFalse( any(l is element for element in gc.get_objects(generation=2)) ) - gc.collect(generation=1) - self.assertFalse( - any(l is element for element in gc.get_objects(generation=0)) - ) - self.assertFalse( - any(l is element for element in gc.get_objects(generation=1)) - ) - self.assertTrue( - any(l is element for element in gc.get_objects(generation=2)) - ) gc.collect(generation=2) self.assertFalse( any(l is element for element in gc.get_objects(generation=0)) @@ -1076,6 +1058,56 @@ class GCTests(unittest.TestCase): callback.assert_not_called() gc.enable() + @unittest.skipIf(Py_GIL_DISABLED, "Free threading does not support incremental GC") + def test_incremental_gc_handles_fast_cycle_creation(self): + + class LinkedList: + + #Use slots to reduce number of implicit objects + __slots__ = "next", "prev", "surprise" + + def __init__(self, next=None, prev=None): + self.next = next + if next is not None: + next.prev = self + self.prev = prev + if prev is not None: + prev.next = self + + def make_ll(depth): + head = LinkedList() + for i in range(depth): + head = LinkedList(head, head.prev) + return head + + head = make_ll(10000) + count = 10000 + + # We expect the counts to go negative eventually + # as there will some objects we aren't counting, + # e.g. the gc stats dicts. The test merely checks + # that the counts don't grow. + + enabled = gc.isenabled() + gc.enable() + olds = [] + for i in range(1000): + newhead = make_ll(200) + count += 200 + newhead.surprise = head + olds.append(newhead) + if len(olds) == 50: + stats = gc.get_stats() + young = stats[0] + incremental = stats[1] + old = stats[2] + collected = young['collected'] + incremental['collected'] + old['collected'] + live = count - collected + self.assertLess(live, 25000) + del olds[:] + if not enabled: + gc.disable() + class GCCallbackTests(unittest.TestCase): def setUp(self): |