Skip to content
Closed
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 22 additions & 39 deletions Lib/test/test_perf_profiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
assert_python_failure,
assert_python_ok,
)
from test.support.os_helper import temp_dir
from test.support.os_helper import temp_dir, unlink


if not support.has_subprocess_support:
Expand All @@ -35,17 +35,10 @@ def supports_trampoline_profiling():


class TestPerfTrampoline(unittest.TestCase):
def setUp(self):
super().setUp()
self.perf_files = set(pathlib.Path("/tmp/").glob("perf-*.map"))

def tearDown(self) -> None:
super().tearDown()
files_to_delete = (
set(pathlib.Path("/tmp/").glob("perf-*.map")) - self.perf_files
)
for file in files_to_delete:
file.unlink()

def _cleanup_perf_map(self, pid):
"""Helper to safely delete a specific perf map file."""
unlink(f"/tmp/perf-{pid}.map")

@unittest.skipIf(support.check_bolt_optimized(), "fails on BOLT instrumented binaries")
def test_trampoline_works(self):
Expand All @@ -64,13 +57,15 @@ def baz():
with temp_dir() as script_dir:
script = make_script(script_dir, "perftest", code)
env = {**os.environ, "PYTHON_JIT": "0"}

Comment thread
picnixz marked this conversation as resolved.
Outdated
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can now remove the extra blank line.

with subprocess.Popen(
[sys.executable, "-Xperf", script],
text=True,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
env=env,
) as process:
self.addCleanup(self._cleanup_perf_map, process.pid)
stdout, stderr = process.communicate()

self.assertEqual(stderr, "")
Expand Down Expand Up @@ -140,11 +135,15 @@ def baz():
stdout=subprocess.PIPE,
env=env,
) as process:
self.addCleanup(self._cleanup_perf_map, process.pid)
stdout, stderr = process.communicate()

self.assertEqual(process.returncode, 0)
self.assertEqual(stderr, "")

child_pid = int(stdout.strip())
self.addCleanup(self._cleanup_perf_map, child_pid)

perf_file = pathlib.Path(f"/tmp/perf-{process.pid}.map")
perf_child_file = pathlib.Path(f"/tmp/perf-{child_pid}.map")
self.assertTrue(perf_file.exists())
Expand Down Expand Up @@ -199,6 +198,7 @@ def baz():
stdout=subprocess.PIPE,
env=env,
) as process:
self.addCleanup(self._cleanup_perf_map, process.pid)
stdout, stderr = process.communicate()

self.assertEqual(stderr, "")
Expand Down Expand Up @@ -276,7 +276,6 @@ def perf_command_works():
if "perf.data" not in stdout:
return False

# Check that we can run a simple perf run
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep existing comments since they are unrelated to the PR.

with temp_dir() as script_dir:
try:
output_file = script_dir + "/perf_output.perf"
Expand Down Expand Up @@ -358,7 +357,6 @@ def run_perf(cwd, *args, use_jit=False, **env_vars):
if proc.returncode:
print(proc.stderr, file=sys.stderr)
raise ValueError(f"Perf failed with return code {proc.returncode}")
# Copy the jit_output_file to the output_file
os.rename(jit_output_file, output_file)

base_cmd = ("perf", "script")
Expand Down Expand Up @@ -434,23 +432,16 @@ def baz(n):
"Unwinding is unreliable with frame pointers",
)
class TestPerfProfiler(unittest.TestCase, TestPerfProfilerMixin):

def _cleanup_perf_map(self, pid):
"""Helper to safely delete a specific perf map file."""
unlink(f"/tmp/perf-{pid}.map")

def run_perf(self, script_dir, script, activate_trampoline=True):
if activate_trampoline:
return run_perf(script_dir, sys.executable, "-Xperf", script)
return run_perf(script_dir, sys.executable, script)

def setUp(self):
super().setUp()
self.perf_files = set(pathlib.Path("/tmp/").glob("perf-*.map"))

def tearDown(self) -> None:
super().tearDown()
files_to_delete = (
set(pathlib.Path("/tmp/").glob("perf-*.map")) - self.perf_files
)
for file in files_to_delete:
file.unlink()

def test_pre_fork_compile(self):
code = """if 1:
import sys
Expand Down Expand Up @@ -499,11 +490,15 @@ def compile_trampolines_for_all_functions():
stdout=subprocess.PIPE,
env=env,
) as process:
self.addCleanup(self._cleanup_perf_map, process.pid)
stdout, stderr = process.communicate()

self.assertEqual(process.returncode, 0)
self.assertNotIn("Error:", stderr)

Copy link
Copy Markdown
Member

@picnixz picnixz Nov 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this blank line (IOW, don't change blank lines)

child_pid = int(stdout.strip())
self.addCleanup(self._cleanup_perf_map, child_pid)

perf_file = pathlib.Path(f"/tmp/perf-{process.pid}.map")
perf_child_file = pathlib.Path(f"/tmp/perf-{child_pid}.map")
self.assertTrue(perf_file.exists())
Expand Down Expand Up @@ -550,26 +545,14 @@ def _is_perf_version_at_least(major, minor):
_is_perf_version_at_least(6, 6), "perf command may not work due to a perf bug"
)
class TestPerfProfilerWithDwarf(unittest.TestCase, TestPerfProfilerMixin):

def run_perf(self, script_dir, script, activate_trampoline=True):
if activate_trampoline:
return run_perf(
script_dir, sys.executable, "-Xperf_jit", script, use_jit=True
)
return run_perf(script_dir, sys.executable, script, use_jit=True)

def setUp(self):
super().setUp()
self.perf_files = set(pathlib.Path("/tmp/").glob("jit*.dump"))
self.perf_files |= set(pathlib.Path("/tmp/").glob("jitted-*.so"))
Comment on lines -562 to -563
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those files are no more deleted. So the same should be done for jit-related files.


def tearDown(self) -> None:
super().tearDown()
files_to_delete = set(pathlib.Path("/tmp/").glob("jit*.dump"))
files_to_delete |= set(pathlib.Path("/tmp/").glob("jitted-*.so"))
files_to_delete = files_to_delete - self.perf_files
for file in files_to_delete:
file.unlink()


if __name__ == "__main__":
unittest.main()
Loading