Skip to content

Commit 7cbd394

Browse files
committed
fixup! Allow perf to work without frame pointers
1 parent 2f6fede commit 7cbd394

File tree

3 files changed

+46
-33
lines changed

3 files changed

+46
-33
lines changed

Lib/test/test_perf_profiler.py

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,29 @@ def baz(n):
383383
self.assertNotIn(f"py::bar:{script}", stdout)
384384
self.assertNotIn(f"py::baz:{script}", stdout)
385385

386+
@unittest.skipUnless(perf_command_works(), "perf command doesn't work")
387+
@unittest.skipUnless(
388+
is_unwinding_reliable_with_frame_pointers(),
389+
"Unwinding is unreliable with frame pointers",
390+
)
391+
class TestPerfProfiler(unittest.TestCase, TestPerfProfilerMixin):
392+
def run_perf(self, script_dir, script, activate_trampoline=True):
393+
if activate_trampoline:
394+
return run_perf(script_dir, sys.executable, "-Xperf", script)
395+
return run_perf(script_dir, sys.executable, script)
396+
397+
def setUp(self):
398+
super().setUp()
399+
self.perf_files = set(pathlib.Path("/tmp/").glob("perf-*.map"))
400+
401+
def tearDown(self) -> None:
402+
super().tearDown()
403+
files_to_delete = (
404+
set(pathlib.Path("/tmp/").glob("perf-*.map")) - self.perf_files
405+
)
406+
for file in files_to_delete:
407+
file.unlink()
408+
386409
def test_pre_fork_compile(self):
387410
code = """if 1:
388411
import sys
@@ -400,7 +423,7 @@ def bar_fork():
400423
foo_fork()
401424
402425
def foo():
403-
pass
426+
import time; time.sleep(1)
404427
405428
def bar():
406429
foo()
@@ -457,30 +480,6 @@ def compile_trampolines_for_all_functions():
457480
self.assertIn(line, child_perf_file_contents)
458481

459482

460-
@unittest.skipUnless(perf_command_works(), "perf command doesn't work")
461-
@unittest.skipUnless(
462-
is_unwinding_reliable_with_frame_pointers(),
463-
"Unwinding is unreliable with frame pointers",
464-
)
465-
class TestPerfProfiler(unittest.TestCase, TestPerfProfilerMixin):
466-
def run_perf(self, script_dir, script, activate_trampoline=True):
467-
if activate_trampoline:
468-
return run_perf(script_dir, sys.executable, "-Xperf", script)
469-
return run_perf(script_dir, sys.executable, script)
470-
471-
def setUp(self):
472-
super().setUp()
473-
self.perf_files = set(pathlib.Path("/tmp/").glob("perf-*.map"))
474-
475-
def tearDown(self) -> None:
476-
super().tearDown()
477-
files_to_delete = (
478-
set(pathlib.Path("/tmp/").glob("perf-*.map")) - self.perf_files
479-
)
480-
for file in files_to_delete:
481-
file.unlink()
482-
483-
484483
@unittest.skipUnless(perf_command_works(), "perf command doesn't work")
485484
class TestPerfProfilerWithDwarf(unittest.TestCase, TestPerfProfilerMixin):
486485
def run_perf(self, script_dir, script, activate_trampoline=True):

Python/perf_trampoline.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ static int perf_map_fini(void* state) {
318318
// clean up the lock and state
319319
PyThread_free_lock(perf_map_state.map_lock);
320320
perf_map_state.perf_map = NULL;
321+
trampoline_api.state = NULL;
321322
}
322323
return 0;
323324
}
@@ -655,6 +656,7 @@ static int perf_map_jit_fini(void* state) {
655656
if (perf_jit_map_state.mapped_buffer != NULL) {
656657
munmap(perf_jit_map_state.mapped_buffer, perf_jit_map_state.mapped_size);
657658
}
659+
trampoline_api.state = NULL;
658660
return 0;
659661
}
660662

@@ -807,6 +809,9 @@ py_trampoline_evaluator(PyThreadState *ts, _PyInterpreterFrame *frame,
807809
int PyUnstable_PerfTrampoline_CompileCode(PyCodeObject *co)
808810
{
809811
#ifdef PY_HAVE_PERF_TRAMPOLINE
812+
if (perf_status != PERF_STATUS_OK) {
813+
return -1;
814+
}
810815
py_trampoline f = NULL;
811816
assert(extra_code_index != -1);
812817
int ret = _PyCode_GetExtra((PyObject *)co, extra_code_index, (void **)&f);
@@ -911,6 +916,16 @@ _PyPerfTrampoline_Init(int activate)
911916
perf_status = PERF_STATUS_OK;
912917
}
913918

919+
if (trampoline_api.init_state) {
920+
trampoline_api.state = trampoline_api.init_state();
921+
if (trampoline_api.state == NULL) {
922+
return -1;
923+
}
924+
}
925+
else {
926+
trampoline_api.state = NULL;
927+
}
928+
914929
#endif
915930
return 0;
916931
}
@@ -947,15 +962,17 @@ _PyPerfTrampoline_AfterFork_Child(void)
947962
char filename[256];
948963
pid_t parent_pid = getppid();
949964
snprintf(filename, sizeof(filename), "/tmp/perf-%d.map", parent_pid);
950-
if (PyUnstable_CopyPerfMapFile(filename) != 0) {
965+
if ( PyUnstable_CopyPerfMapFile(filename) != 0) {
951966
return PyStatus_Error("Failed to copy perf map file.");
952967
}
953968
} else {
969+
PyUnstable_PerfMapState_Fini();
954970
// Restart trampoline in file in child.
955971
int was_active = _PyIsPerfTrampolineActive();
956972
_PyPerfTrampoline_Fini();
957973
if (was_active) {
958974
_PyPerfTrampoline_Init(1);
975+
trampoline_api.init_state();
959976
}
960977
}
961978
#endif

Python/sysmodule.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2379,13 +2379,10 @@ PyAPI_FUNC(void) PyUnstable_PerfMapState_Fini(void) {
23792379

23802380
PyAPI_FUNC(int) PyUnstable_CopyPerfMapFile(const char* parent_filename) {
23812381
#ifndef MS_WINDOWS
2382-
void *state = _PyPerfTrampoline_GetState();
2383-
if (state) {
2384-
_PyPerf_Callbacks cur_cb;
2385-
_PyPerfTrampoline_GetCallbacks(&cur_cb);
2386-
if (cur_cb.copy_file != NULL) {
2387-
cur_cb.copy_file(parent_filename);
2388-
}
2382+
_PyPerf_Callbacks cur_cb;
2383+
_PyPerfTrampoline_GetCallbacks(&cur_cb);
2384+
if (cur_cb.copy_file != NULL) {
2385+
cur_cb.copy_file(parent_filename);
23892386
}
23902387
#endif
23912388
return 0;

0 commit comments

Comments
 (0)