@@ -931,23 +931,29 @@ def run_cyclic(rng, collections_per_phase=5, cycles=2):
931931 def test_walker_settles_differently_per_workload (self ):
932932 """Different workloads must produce different final worker counts.
933933
934- Run 30 dense collections (200K objects) → record W1.
935- Run 30 simple collections (5K objects) → record W2.
934+ Run 50 dense collections (200K objects) → record W1.
935+ Run 50 simple collections (5K objects) → record W2.
936936 Assert W1 != W2.
937937
938938 This proves the walker ADAPTS to workload, not just explores
939939 randomly. A fixed controller or cost-blind PRNG cannot reliably
940- pass this — the worker count after 30 dense collections should
941- be different from after 30 simple collections because the
940+ pass this — the worker count after 50 dense collections should
941+ be different from after 50 simple collections because the
942942 performance landscape is different.
943943 """
944944 import random
945945 rng = random .Random (42 )
946946
947+ try :
948+ gc .disable_parallel ()
949+ except (ValueError , RuntimeError ):
950+ pass
947951 gc .enable_parallel (8 )
948952
949953 # Phase 1: dense collections (200K objects, graph traversal)
950- for _ in range (30 ):
954+ # 50 collections gives the unbiased (50/50) walker enough steps
955+ # to differentiate between workloads reliably.
956+ for _ in range (50 ):
951957 nodes = [{'id' : i , 'refs' : []} for i in range (200_000 )]
952958 for i in range (0 , len (nodes ), 50 ):
953959 targets = rng .sample (range (len (nodes )), min (3 , len (nodes )))
@@ -958,7 +964,7 @@ def test_walker_settles_differently_per_workload(self):
958964 W1 = gc .get_parallel_config ()['adaptive_workers' ]
959965
960966 # Phase 2: simple collections (5K objects, chains)
961- for _ in range (30 ):
967+ for _ in range (50 ):
962968 objs = [{'ref' : None } for _ in range (5_000 )]
963969 for i in range (len (objs ) - 1 ):
964970 objs [i ]['ref' ] = objs [i + 1 ]
@@ -995,6 +1001,10 @@ def test_rapid_collections_varying_heaps(self):
9951001 """
9961002 import random
9971003 rng = random .Random (42 )
1004+ try :
1005+ gc .disable_parallel ()
1006+ except (ValueError , RuntimeError ):
1007+ pass
9981008 gc .enable_parallel (8 )
9991009
10001010 for i in range (200 ):
@@ -1016,6 +1026,10 @@ def test_enable_disable_cycles(self):
10161026 the condvar init/fini paths and catches races in shutdown.
10171027 """
10181028 for num_workers in [2 , 4 , 8 , 3 , 6 , 2 , 8 , 4 ]:
1029+ try :
1030+ gc .disable_parallel ()
1031+ except (ValueError , RuntimeError ):
1032+ pass
10191033 gc .enable_parallel (num_workers )
10201034 # Run a few collections at this worker count
10211035 for _ in range (10 ):
@@ -1035,7 +1049,6 @@ def test_concurrent_allocation_during_gc(self):
10351049 with application threads. The condvar dispatch must not deadlock
10361050 when the GIL is contended.
10371051 """
1038- import time
10391052
10401053 stop = threading .Event ()
10411054 errors = []
@@ -1052,6 +1065,10 @@ def allocator():
10521065 except Exception as e :
10531066 errors .append (e )
10541067
1068+ try :
1069+ gc .disable_parallel ()
1070+ except (ValueError , RuntimeError ):
1071+ pass
10551072 gc .enable_parallel (8 )
10561073
10571074 # Start allocator threads
@@ -1079,6 +1096,10 @@ def test_walker_transitions_through_range(self):
10791096 to tiny heap (walker drops). This ensures the condvar dispatch
10801097 exercises N=2 through N=8 over the test run.
10811098 """
1099+ try :
1100+ gc .disable_parallel ()
1101+ except (ValueError , RuntimeError ):
1102+ pass
10821103 gc .enable_parallel (8 )
10831104 all_aw = set ()
10841105
0 commit comments