aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python/perf_trampoline.c
diff options
context:
space:
mode:
authorgsallam <123525874+gsallam@users.noreply.github.com>2023-10-26 20:57:29 -0700
committerGitHub <noreply@github.com>2023-10-27 03:57:29 +0000
commit21f068d80c6cc5de75f9df70fdd733d0ce9c70de (patch)
treedaceefb593efea137dd642df968075b24c6d52f8 /Python/perf_trampoline.c
parent3d2f1f0b830d86f16f42c42b54d3ea4453dac318 (diff)
downloadcpython-21f068d80c6cc5de75f9df70fdd733d0ce9c70de.tar.gz
cpython-21f068d80c6cc5de75f9df70fdd733d0ce9c70de.zip
gh-109587: Allow "precompiled" perf-trampolines to largely mitigate the cost of enabling perf-trampolines (#109666)
Diffstat (limited to 'Python/perf_trampoline.c')
-rw-r--r--Python/perf_trampoline.c50
1 files changed, 44 insertions, 6 deletions
diff --git a/Python/perf_trampoline.c b/Python/perf_trampoline.c
index 209a23b6c1c..491223924ed 100644
--- a/Python/perf_trampoline.c
+++ b/Python/perf_trampoline.c
@@ -193,7 +193,7 @@ typedef struct trampoline_api_st trampoline_api_t;
#define perf_code_arena _PyRuntime.ceval.perf.code_arena
#define trampoline_api _PyRuntime.ceval.perf.trampoline_api
#define perf_map_file _PyRuntime.ceval.perf.map_file
-
+#define persist_after_fork _PyRuntime.ceval.perf.persist_after_fork
static void
perf_map_write_entry(void *state, const void *code_addr,
@@ -361,6 +361,26 @@ default_eval:
}
#endif // PY_HAVE_PERF_TRAMPOLINE
+int PyUnstable_PerfTrampoline_CompileCode(PyCodeObject *co)
+{
+#ifdef PY_HAVE_PERF_TRAMPOLINE
+ py_trampoline f = NULL;
+ assert(extra_code_index != -1);
+ int ret = _PyCode_GetExtra((PyObject *)co, extra_code_index, (void **)&f);
+ if (ret != 0 || f == NULL) {
+ py_trampoline new_trampoline = compile_trampoline();
+ if (new_trampoline == NULL) {
+ return 0;
+ }
+ trampoline_api.write_state(trampoline_api.state, new_trampoline,
+ perf_code_arena->code_size, co);
+ return _PyCode_SetExtra((PyObject *)co, extra_code_index,
+ (void *)new_trampoline);
+ }
+#endif // PY_HAVE_PERF_TRAMPOLINE
+ return 0;
+}
+
int
_PyIsPerfTrampolineActive(void)
{
@@ -448,16 +468,34 @@ _PyPerfTrampoline_Fini(void)
return 0;
}
+int
+PyUnstable_PerfTrampoline_SetPersistAfterFork(int enable){
+#ifdef PY_HAVE_PERF_TRAMPOLINE
+ persist_after_fork = enable;
+ return persist_after_fork;
+#endif
+ return 0;
+}
+
PyStatus
_PyPerfTrampoline_AfterFork_Child(void)
{
#ifdef PY_HAVE_PERF_TRAMPOLINE
- // Restart trampoline in file in child.
- int was_active = _PyIsPerfTrampolineActive();
- _PyPerfTrampoline_Fini();
PyUnstable_PerfMapState_Fini();
- if (was_active) {
- _PyPerfTrampoline_Init(1);
+ if (persist_after_fork) {
+ char filename[256];
+ pid_t parent_pid = getppid();
+ snprintf(filename, sizeof(filename), "/tmp/perf-%d.map", parent_pid);
+ if (PyUnstable_CopyPerfMapFile(filename) != 0) {
+ return PyStatus_Error("Failed to copy perf map file.");
+ }
+ } else {
+ // Restart trampoline in file in child.
+ int was_active = _PyIsPerfTrampolineActive();
+ _PyPerfTrampoline_Fini();
+ if (was_active) {
+ _PyPerfTrampoline_Init(1);
+ }
}
#endif
return PyStatus_Ok();