| # Run by test_gc. |
| from test import support |
| import _testinternalcapi |
| import gc |
| import unittest |
| |
| class IncrementalGCTests(unittest.TestCase): |
| |
| # Use small increments to emulate longer running process in a shorter time |
| @support.gc_threshold(200, 10) |
| 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(1000) |
| |
| assert(gc.isenabled()) |
| olds = [] |
| initial_heap_size = _testinternalcapi.get_tracked_heap_size() |
| for i in range(20_000): |
| newhead = make_ll(20) |
| newhead.surprise = head |
| olds.append(newhead) |
| if len(olds) == 20: |
| new_objects = _testinternalcapi.get_tracked_heap_size() - initial_heap_size |
| self.assertLess(new_objects, 27_000, f"Heap growing. Reached limit after {i} iterations") |
| del olds[:] |
| |
| |
| if __name__ == "__main__": |
| unittest.main() |