| .. highlight:: c | |
| .. _perfmaps: | |
| Support for Perf Maps | |
| ---------------------- | |
| On supported platforms (Linux and macOS), the runtime can take | |
| advantage of *perf map files* to make Python functions visible to an external | |
| profiling tool (such as `perf <https://perf.wiki.kernel.org/index.php/Main_Page>`_ or | |
| `samply <https://github.com/mstange/samply/>`_). A running process may create a | |
| file in the ``/tmp`` directory, which contains entries that can map a section | |
| of executable code to a name. This interface is described in the | |
| `documentation of the Linux Perf tool <https://git.kernel.org/pub/scm/linux/ | |
| kernel/git/torvalds/linux.git/tree/tools/perf/Documentation/jit-interface.txt>`_. | |
| In Python, these helper APIs can be used by libraries and features that rely | |
| on generating machine code on the fly. | |
| Note that holding an :term:`attached thread state` is not required for these APIs. | |
| .. c:function:: int PyUnstable_PerfMapState_Init(void) | |
| Open the ``/tmp/perf-$pid.map`` file, unless it's already opened, and create | |
| a lock to ensure thread-safe writes to the file (provided the writes are | |
| done through :c:func:`PyUnstable_WritePerfMapEntry`). Normally, there's no need | |
| to call this explicitly; just use :c:func:`PyUnstable_WritePerfMapEntry` | |
| and it will initialize the state on first call. | |
| Returns ``0`` on success, ``-1`` on failure to create/open the perf map file, | |
| or ``-2`` on failure to create a lock. Check ``errno`` for more information | |
| about the cause of a failure. | |
| .. c:function:: int PyUnstable_WritePerfMapEntry(const void *code_addr, size_t code_size, const char *entry_name) | |
| Write one single entry to the ``/tmp/perf-$pid.map`` file. This function is | |
| thread safe. Here is what an example entry looks like:: | |
| # address size name | |
| 7f3529fcf759 b py::bar:/run/t.py | |
| Will call :c:func:`PyUnstable_PerfMapState_Init` before writing the entry, if | |
| the perf map file is not already opened. Returns ``0`` on success, or the | |
| same error codes as :c:func:`PyUnstable_PerfMapState_Init` on failure. | |
| .. c:function:: void PyUnstable_PerfMapState_Fini(void) | |
| Close the perf map file opened by :c:func:`PyUnstable_PerfMapState_Init`. | |
| This is called by the runtime itself during interpreter shut-down. In | |
| general, there shouldn't be a reason to explicitly call this, except to | |
| handle specific scenarios such as forking. | |
| .. c:function:: int PyUnstable_CopyPerfMapFile(const char *parent_filename) | |
| Open the ``/tmp/perf-$pid.map`` file and append the content of *parent_filename* | |
| to it. | |
| This function is available on all platforms but only generates output on platforms | |
| that support perf maps (currently only Linux). On other platforms, it does nothing. | |
| .. versionadded:: 3.13 | |
| .. c:function:: int PyUnstable_PerfTrampoline_CompileCode(PyCodeObject *code) | |
| Compile the given code object using the current perf trampoline. | |
| The "current" trampoline is the one set by the runtime or the most recent | |
| :c:func:`PyUnstable_PerfTrampoline_SetPersistAfterFork` call. | |
| If no trampoline is set, falls back to normal compilation (no perf map entry). | |
| :param code: The code object to compile. | |
| :return: 0 on success, -1 on failure. | |
| .. versionadded:: 3.13 | |
| .. c:function:: int PyUnstable_PerfTrampoline_SetPersistAfterFork(int enable) | |
| Set whether the perf trampoline should persist after a fork. | |
| * If ``enable`` is true (non-zero): perf map file remains open/valid post-fork. | |
| Child process inherits all existing perf map entries. | |
| * If ``enable`` is false (zero): perf map closes post-fork. | |
| Child process gets empty perf map. | |
| Default: false (clears on fork). | |
| :param enable: 1 to enable, 0 to disable. | |
| :return: 0 on success, -1 on failure. | |
| .. versionadded:: 3.13 |