summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_gc.py
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2024-03-20 08:54:42 (GMT)
committerGitHub <noreply@github.com>2024-03-20 08:54:42 (GMT)
commit15309329b65a285cb7b3071f0f08ac964b61411b (patch)
tree83b5be564755d7ea396c76eda29e6d33faf535d9 /Lib/test/test_gc.py
parentd5ebf8b71fd18d7a1f2f6b670a2c18749dc2b55e (diff)
downloadcpython-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.py72
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):