|
1 | 1 | import os |
2 | 2 | import sys |
3 | 3 | import warnings |
| 4 | +from array import array |
4 | 5 | from inspect import isabstract |
5 | 6 | from typing import Any |
6 | 7 | import linecache |
@@ -100,24 +101,20 @@ def runtest_refleak(test_name, test_func, |
100 | 101 | for obj in ByteString.__subclasses__() + [ByteString]: # type: ignore[attr-defined] |
101 | 102 | abcs[obj] = _get_dump(obj)[0] |
102 | 103 |
|
103 | | - # bpo-31217: Integer pool to get a single integer object for the same |
104 | | - # value. The pool is used to prevent false alarm when checking for memory |
105 | | - # block leaks. Fill the pool with values in -1000..1000 which are the most |
106 | | - # common (reference, memory block, file descriptor) differences. |
107 | | - int_pool = {value: value for value in range(-1000, 1000)} |
108 | | - def get_pooled_int(value): |
109 | | - return int_pool.setdefault(value, value) |
110 | | - |
111 | 104 | warmups = hunt_refleak.warmups |
112 | 105 | runs = hunt_refleak.runs |
113 | 106 | filename = hunt_refleak.filename |
114 | 107 | repcount = warmups + runs |
115 | 108 |
|
116 | | - # Pre-allocate to ensure that the loop doesn't allocate anything new |
| 109 | + # Pre-allocate to ensure that the loop doesn't allocate anything new. |
| 110 | + # Store the deltas as raw values in arrays rather than as int objects in |
| 111 | + # lists: each unique delta stored as an object would live until the end of |
| 112 | + # the loop and show up in the following repetition's reference and memory |
| 113 | + # block deltas (bpo-31217, gh-155981). |
117 | 114 | rep_range = list(range(repcount)) |
118 | | - rc_deltas = [0] * repcount |
119 | | - alloc_deltas = [0] * repcount |
120 | | - fd_deltas = [0] * repcount |
| 115 | + rc_deltas = array('q', [0]) * repcount |
| 116 | + alloc_deltas = array('q', [0]) * repcount |
| 117 | + fd_deltas = array('q', [0]) * repcount |
121 | 118 | getallocatedblocks = sys.getallocatedblocks |
122 | 119 | gettotalrefcount = sys.gettotalrefcount |
123 | 120 | getunicodeinternedsize = sys.getunicodeinternedsize |
@@ -161,12 +158,11 @@ def get_pooled_int(value): |
161 | 158 | rc_after = gettotalrefcount() |
162 | 159 | fd_after = fd_count() |
163 | 160 |
|
164 | | - rc_deltas[i] = get_pooled_int(rc_after - rc_before) |
165 | | - alloc_deltas[i] = get_pooled_int(alloc_after - alloc_before) |
166 | | - fd_deltas[i] = get_pooled_int(fd_after - fd_before) |
| 161 | + rc_deltas[i] = rc_after - rc_before |
| 162 | + alloc_deltas[i] = alloc_after - alloc_before |
| 163 | + fd_deltas[i] = fd_after - fd_before |
167 | 164 |
|
168 | 165 | if not quiet: |
169 | | - # use max, not sum, so total_leaks is one of the pooled ints |
170 | 166 | total_leaks = max(rc_deltas[i], alloc_deltas[i], fd_deltas[i]) |
171 | 167 | if total_leaks <= 0: |
172 | 168 | symbol = '.' |
@@ -217,8 +213,8 @@ def check_fd_deltas(deltas): |
217 | 213 | (alloc_deltas, 'memory blocks', check_rc_deltas), |
218 | 214 | (fd_deltas, 'file descriptors', check_fd_deltas) |
219 | 215 | ]: |
220 | | - # ignore warmup runs |
221 | | - deltas = deltas[warmups:] |
| 216 | + # ignore warmup runs; convert to a list for reporting |
| 217 | + deltas = list(deltas[warmups:]) |
222 | 218 | failing = checker(deltas) |
223 | 219 | suspicious = any(deltas) |
224 | 220 | if failing or suspicious: |
|
0 commit comments