@@ -529,8 +529,6 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
529529
530530 if slaveargs is not None :
531531 args , kwargs = json .loads (slaveargs )
532- if kwargs ['huntrleaks' ]:
533- warm_caches ()
534532 if testdir :
535533 kwargs ['testdir' ] = testdir
536534 try :
@@ -541,9 +539,6 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
541539 print json .dumps (result )
542540 sys .exit (0 )
543541
544- if huntrleaks :
545- warm_caches ()
546-
547542 good = []
548543 bad = []
549544 skipped = []
@@ -1332,7 +1327,7 @@ def runtest_inner(test, verbose, quiet, huntrleaks=False, pgo=False, testdir=Non
13321327 indirect_test = getattr (the_module , "test_main" , None )
13331328 if huntrleaks :
13341329 refleak = dash_R (the_module , test , indirect_test ,
1335- huntrleaks )
1330+ huntrleaks , quiet )
13361331 else :
13371332 if indirect_test is not None :
13381333 indirect_test ()
@@ -1425,7 +1420,7 @@ def cleanup_test_droppings(testname, verbose):
14251420 print >> sys .stderr , ("%r left behind %s %r and it couldn't be "
14261421 "removed: %s" % (testname , kind , name , msg ))
14271422
1428- def dash_R (the_module , test , indirect_test , huntrleaks ):
1423+ def dash_R (the_module , test , indirect_test , huntrleaks , quiet ):
14291424 """Run a test multiple times, looking for reference leaks.
14301425
14311426 Returns:
@@ -1438,6 +1433,10 @@ def dash_R(the_module, test, indirect_test, huntrleaks):
14381433 raise Exception ("Tracking reference leaks requires a debug build "
14391434 "of Python" )
14401435
1436+ # Avoid false positives due to various caches
1437+ # filling slowly with random data:
1438+ warm_caches ()
1439+
14411440 # Save current values for dash_R_cleanup() to restore.
14421441 fs = warnings .filters [:]
14431442 ps = copy_reg .dispatch_table .copy ()
@@ -1457,6 +1456,14 @@ def dash_R(the_module, test, indirect_test, huntrleaks):
14571456 for obj in abc .__subclasses__ () + [abc ]:
14581457 abcs [obj ] = obj ._abc_registry .copy ()
14591458
1459+ # bpo-31217: Integer pool to get a single integer object for the same
1460+ # value. The pool is used to prevent false alarm when checking for memory
1461+ # block leaks. Fill the pool with values in -1000..1000 which are the most
1462+ # common (reference, memory block, file descriptor) differences.
1463+ int_pool = {value : value for value in range (- 1000 , 1000 )}
1464+ def get_pooled_int (value ):
1465+ return int_pool .setdefault (value , value )
1466+
14601467 if indirect_test :
14611468 def run_the_test ():
14621469 indirect_test ()
@@ -1467,27 +1474,39 @@ def run_the_test():
14671474 deltas = []
14681475 nwarmup , ntracked , fname = huntrleaks
14691476 fname = os .path .join (support .SAVEDCWD , fname )
1477+
1478+ # Pre-allocate to ensure that the loop doesn't allocate anything new
14701479 repcount = nwarmup + ntracked
1471- rc_deltas = [0 ] * ntracked
1472- fd_deltas = [0 ] * ntracked
1480+ rc_deltas = [0 ] * repcount
1481+ fd_deltas = [0 ] * repcount
1482+ rep_range = list (range (repcount ))
1483+
1484+ if not quiet :
1485+ print >> sys .stderr , "beginning" , repcount , "repetitions"
1486+ print >> sys .stderr , ("1234567890" * (repcount // 10 + 1 ))[:repcount ]
14731487
1474- print >> sys .stderr , "beginning" , repcount , "repetitions"
1475- print >> sys .stderr , ("1234567890" * (repcount // 10 + 1 ))[:repcount ]
14761488 dash_R_cleanup (fs , ps , pic , zdc , abcs )
1489+
14771490 # initialize variables to make pyflakes quiet
14781491 rc_before = fd_before = 0
1479- for i in range (repcount ):
1492+
1493+ for i in rep_range :
14801494 run_the_test ()
1481- sys .stderr .write ('.' )
1495+
1496+ if not quiet :
1497+ sys .stderr .write ('.' )
1498+
14821499 dash_R_cleanup (fs , ps , pic , zdc , abcs )
1500+
14831501 rc_after = sys .gettotalrefcount ()
14841502 fd_after = support .fd_count ()
1485- if i >= nwarmup :
1486- rc_deltas [i - nwarmup ] = rc_after - rc_before
1487- fd_deltas [i - nwarmup ] = fd_after - fd_before
1503+ rc_deltas [i ] = get_pooled_int (rc_after - rc_before )
1504+ fd_deltas [i ] = get_pooled_int (fd_after - fd_before )
14881505 rc_before = rc_after
14891506 fd_before = fd_after
1490- print >> sys .stderr
1507+
1508+ if not quiet :
1509+ print >> sys .stderr
14911510
14921511 # These checkers return False on success, True on failure
14931512 def check_rc_deltas (deltas ):
@@ -1513,6 +1532,7 @@ def check_fd_deltas(deltas):
15131532 (rc_deltas , 'references' , check_rc_deltas ),
15141533 (fd_deltas , 'file descriptors' , check_fd_deltas )
15151534 ]:
1535+ deltas = deltas [nwarmup :]
15161536 if checker (deltas ):
15171537 msg = '%s leaked %s %s, sum=%s' % (test , deltas , item_name , sum (deltas ))
15181538 print >> sys .stderr , msg
@@ -1647,7 +1667,7 @@ def clear_caches():
16471667 ctypes ._reset_cache ()
16481668
16491669 # Collect cyclic trash.
1650- gc . collect ()
1670+ support . gc_collect ()
16511671
16521672def warm_caches ():
16531673 """Create explicitly internal singletons which are created on demand
0 commit comments