mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
gh-138122: Make sampling profiler integration tests more resilient (#142382)
The tests were flaky on slow machines because subprocesses could finish before enough samples were collected. This adds synchronization similar to test_external_inspection: test scripts now signal when they start working, and the profiler waits for this signal before sampling. Test scripts now run in infinite loops until killed rather than for fixed iterations, ensuring the profiler always has active work to sample regardless of machine speed.
This commit is contained in:
parent
ff2577f56e
commit
ef51a7c8f3
4 changed files with 185 additions and 126 deletions
|
|
@ -39,32 +39,26 @@ def setUpClass(cls):
|
|||
import gc
|
||||
|
||||
class ExpensiveGarbage:
|
||||
"""Class that triggers GC with expensive finalizer (callback)."""
|
||||
def __init__(self):
|
||||
self.cycle = self
|
||||
|
||||
def __del__(self):
|
||||
# CPU-intensive work in the finalizer callback
|
||||
result = 0
|
||||
for i in range(100000):
|
||||
result += i * i
|
||||
if i % 1000 == 0:
|
||||
result = result % 1000000
|
||||
|
||||
def main_loop():
|
||||
"""Main loop that triggers GC with expensive callback."""
|
||||
while True:
|
||||
ExpensiveGarbage()
|
||||
gc.collect()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main_loop()
|
||||
_test_sock.sendall(b"working")
|
||||
while True:
|
||||
ExpensiveGarbage()
|
||||
gc.collect()
|
||||
'''
|
||||
|
||||
def test_gc_frames_enabled(self):
|
||||
"""Test that GC frames appear when gc tracking is enabled."""
|
||||
with (
|
||||
test_subprocess(self.gc_test_script) as subproc,
|
||||
test_subprocess(self.gc_test_script, wait_for_working=True) as subproc,
|
||||
io.StringIO() as captured_output,
|
||||
mock.patch("sys.stdout", captured_output),
|
||||
):
|
||||
|
|
@ -94,7 +88,7 @@ def test_gc_frames_enabled(self):
|
|||
def test_gc_frames_disabled(self):
|
||||
"""Test that GC frames do not appear when gc tracking is disabled."""
|
||||
with (
|
||||
test_subprocess(self.gc_test_script) as subproc,
|
||||
test_subprocess(self.gc_test_script, wait_for_working=True) as subproc,
|
||||
io.StringIO() as captured_output,
|
||||
mock.patch("sys.stdout", captured_output),
|
||||
):
|
||||
|
|
@ -133,18 +127,13 @@ def setUpClass(cls):
|
|||
cls.native_test_script = """
|
||||
import operator
|
||||
|
||||
def main_loop():
|
||||
while True:
|
||||
# Native code in the middle of the stack:
|
||||
operator.call(inner)
|
||||
|
||||
def inner():
|
||||
# Python code at the top of the stack:
|
||||
for _ in range(1_000_0000):
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
main_loop()
|
||||
_test_sock.sendall(b"working")
|
||||
while True:
|
||||
operator.call(inner)
|
||||
"""
|
||||
|
||||
def test_native_frames_enabled(self):
|
||||
|
|
@ -154,10 +143,7 @@ def test_native_frames_enabled(self):
|
|||
)
|
||||
self.addCleanup(close_and_unlink, collapsed_file)
|
||||
|
||||
with (
|
||||
test_subprocess(self.native_test_script) as subproc,
|
||||
):
|
||||
# Suppress profiler output when testing file export
|
||||
with test_subprocess(self.native_test_script, wait_for_working=True) as subproc:
|
||||
with (
|
||||
io.StringIO() as captured_output,
|
||||
mock.patch("sys.stdout", captured_output),
|
||||
|
|
@ -199,7 +185,7 @@ def test_native_frames_enabled(self):
|
|||
def test_native_frames_disabled(self):
|
||||
"""Test that native frames do not appear when native tracking is disabled."""
|
||||
with (
|
||||
test_subprocess(self.native_test_script) as subproc,
|
||||
test_subprocess(self.native_test_script, wait_for_working=True) as subproc,
|
||||
io.StringIO() as captured_output,
|
||||
mock.patch("sys.stdout", captured_output),
|
||||
):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue