Skip to content

Commit 41bab32

Browse files
gh-96143: Improve perf profiler docs
1 parent 7b01ce7 commit 41bab32

File tree

7 files changed

+100
-42
lines changed

7 files changed

+100
-42
lines changed

Doc/howto/perf_profiling.rst

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ fly before the execution of every Python function and it will teach ``perf`` the
2525
relationship between this piece of code and the associated Python function using
2626
`perf map files`_.
2727

28-
.. warning::
28+
.. note::
2929

3030
Support for the ``perf`` profiler is only currently available for Linux on
3131
selected architectures. Check the output of the configure build step or
@@ -51,11 +51,11 @@ For example, consider the following script:
5151
if __name__ == "__main__":
5252
baz(1000000)
5353
54-
We can run perf to sample CPU stack traces at 9999 Hertz:
54+
We can run ``perf`` to sample CPU stack traces at 9999 Hertz::
5555

5656
$ perf record -F 9999 -g -o perf.data python my_script.py
5757

58-
Then we can use perf report to analyze the data:
58+
Then we can use ``perf`` report to analyze the data:
5959

6060
.. code-block:: shell-session
6161
@@ -101,7 +101,7 @@ As you can see here, the Python functions are not shown in the output, only ``_P
101101
functions use the same C function to evaluate bytecode so we cannot know which Python function corresponds to which
102102
bytecode-evaluating function.
103103

104-
Instead, if we run the same experiment with perf support activated we get:
104+
Instead, if we run the same experiment with ``perf`` support activated we get:
105105

106106
.. code-block:: shell-session
107107
@@ -147,19 +147,27 @@ Instead, if we run the same experiment with perf support activated we get:
147147
148148
149149
150-
Enabling perf profiling mode
151-
----------------------------
150+
How to enable the ``perf`` profiling mode
151+
-----------------------------------------
152152

153-
There are two main ways to activate the perf profiling mode. If you want it to be
154-
active since the start of the Python interpreter, you can use the `-Xperf` option:
153+
There are three ways to activate the ``perf`` profiling mode:
154+
using the :option:`-Xperf <-X>` command-line option,
155+
using the :envvar:`PYTHONPERFSUPPORT` environment variable,
156+
and using the :func:`sys.activate_stack_trampoline` and
157+
:func:`sys.deactivate_stack_trampoline` APIs.
158+
If you want profiling to be active when you start the Python interpreter,
159+
use the :option:`-Xperf <-X>` option::
155160

156161
$ python -Xperf my_script.py
157162

158-
You can also set the :envvar:`PYTHONPERFSUPPORT` to a nonzero value to actiavate perf
159-
profiling mode globally.
163+
If you need to activate the ``perf`` profiling mode globally,
164+
set the environment variable :envvar:`PYTHONPERFSUPPORT`
165+
to a nonzero value.
160166

161-
There is also support for dynamically activating and deactivating the perf
162-
profiling mode by using the APIs in the :mod:`sys` module:
167+
If you need to dynamically activate and deactivate the ``perf`` profiling mode
168+
in response to a signal or other communication mechanisms with your process,
169+
use the :func:`sys.activate_stack_trampoline` and
170+
:func:`sys.deactivate_stack_trampoline` APIs:
163171

164172
.. code-block:: python
165173
@@ -172,27 +180,22 @@ profiling mode by using the APIs in the :mod:`sys` module:
172180
173181
# Perf profiling is not active anymore
174182
175-
These APIs can be handy if you want to activate/deactivate profiling mode in
176-
response to a signal or other communication mechanism with your process.
177-
178-
179-
180-
Now we can analyze the data with ``perf report``:
183+
Now we can analyze the data with ``perf report``::
181184

182185
$ perf report -g -i perf.data
183186

184187

185188
How to obtain the best results
186-
-------------------------------
189+
------------------------------
187190

188191
For the best results, Python should be compiled with
189192
``CFLAGS="-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"`` as this allows
190193
profilers to unwind using only the frame pointer and not on DWARF debug
191-
information. This is because as the code that is interposed to allow perf
194+
information. This is because as the code that is interposed to allow ``perf``
192195
support is dynamically generated it doesn't have any DWARF debugging information
193196
available.
194197

195-
You can check if you system has been compiled with this flag by running:
198+
You can check if you system has been compiled with this flag by running::
196199

197200
$ python -m sysconfig | grep 'no-omit-frame-pointer'
198201

Doc/library/sys.rst

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,6 +1524,35 @@ always available.
15241524
This function has been added on a provisional basis (see :pep:`411`
15251525
for details.) Use it only for debugging purposes.
15261526

1527+
.. function:: activate_stack_trampoline(backend, /)
1528+
1529+
Activate the stack profiler trampoline *backend*.
1530+
The only supported backend is `"perf"`.
1531+
1532+
.. availability:: Linux.
1533+
1534+
.. versionadded:: 3.12
1535+
1536+
.. seealso::
1537+
1538+
:ref:`perf_profiling`
1539+
1540+
.. function:: deactivate_stack_trampoline()
1541+
1542+
Deactivate the stack profiler trampoline.
1543+
1544+
.. availability:: Linux.
1545+
1546+
.. versionadded:: 3.12
1547+
1548+
.. function:: is_stack_trampoline_active()
1549+
1550+
Return ``True`` if the stack profiler trampoline is active.
1551+
1552+
.. availability:: Linux.
1553+
1554+
.. versionadded:: 3.12
1555+
15271556
.. function:: _enablelegacywindowsfsencoding()
15281557

15291558
Changes the :term:`filesystem encoding and error handler` to 'mbcs' and

Doc/using/cmdline.rst

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -535,12 +535,13 @@ Miscellaneous options
535535
development (running from the source tree) then the default is "off".
536536
Note that the "importlib_bootstrap" and "importlib_bootstrap_external"
537537
frozen modules are always used, even if this flag is set to "off".
538-
* ``-X perf`` to activate compatibility mode with the ``perf`` profiler.
538+
* ``-X perf`` activates compatibility mode with the ``perf`` profiler.
539539
When this option is activated, the Linux ``perf`` profiler will be able to
540540
report Python calls. This option is only available on some platforms and
541541
will do nothing if is not supported on the current system. The default value
542-
is "off". See also :envvar:`PYTHONPERFSUPPORT` and :ref:`perf_profiling`
543-
for more information.
542+
is "off". See :ref:`perf_profiling` for more details.
543+
This option is equivalent to setting the environment variable
544+
:envvar:`PYTHONPERFSUPPORT` to ``1``.
544545

545546
It also allows passing arbitrary values and retrieving them through the
546547
:data:`sys._xoptions` dictionary.
@@ -1036,8 +1037,13 @@ conflict.
10361037
.. envvar:: PYTHONPERFSUPPORT
10371038

10381039
If this variable is set to a nonzero value, it activates compatibility mode
1039-
with the ``perf`` profiler so Python calls can be detected by it. See the
1040-
:ref:`perf_profiling` section for more information.
1040+
with the ``perf`` profiler so Python calls can be detected by it.
1041+
This is exactly equivalent to setting :option:`-X perf <-X>`
1042+
on the command line.
1043+
1044+
If set to ``0``, disable ``perf`` profiler support.
1045+
1046+
See :ref:`perf_profiling` for more details.
10411047

10421048
.. versionadded:: 3.12
10431049

Doc/whatsnew/3.12.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,14 @@ Important deprecations, removals or restrictions:
7474
New Features
7575
============
7676

77+
* Add :ref:`perf_profiling` through the new command-line option
78+
:option:`-X perf <-X>`, as well as the new
79+
:func:`sys.activate_stack_trampoline`,
80+
:func:`sys.deactivate_stack_trampoline`,
81+
and :func:`sys.is_stack_trampoline_active` APIs.
82+
(Contributed by Pablo Galindo and Christian Heimes
83+
with contributions from Gregory P. Smith [Google] and Mark Shannon
84+
in :gh:`96123`.)
7785

7886

7987
Other Language Changes
@@ -126,6 +134,19 @@ sqlite3
126134
(Contributed by Erlend E. Aasland in :gh:`77617`.)
127135

128136

137+
sys
138+
---
139+
140+
* Add :func:`sys.activate_stack_trampoline` and
141+
:func:`sys.deactivate_stack_trampoline` for activating and deactivating
142+
stack profiler trampolines,
143+
and :func:`sys.is_stack_trampoline_active` for querying if stack profiler
144+
trampolines are active.
145+
(Contributed by Pablo Galindo and Christian Heimes
146+
with contributions from Gregory P. Smith [Google] and Mark Shannon
147+
in :gh:`96123`.)
148+
149+
129150
Optimizations
130151
=============
131152

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
Add a new ``-X perf`` Python command line option as well as
2-
:func:`sys.activate_stack_trampoline` and :func:`sys.deactivate_stack_trampoline`
3-
function in the :mod:`sys` module that allows to set/unset the interpreter in a
4-
way that the Linux ``perf`` profiler can detect Python calls. The new
5-
:func:`sys.is_stack_trampoline_active` function allows to query the state of the
6-
perf trampoline. Design by Pablo Galindo. Patch by Pablo Galindo and Christian Heimes
1+
Add :ref:`perf_profiling` through the new command-line option
2+
:option:`-X perf <-X>`, as well as the new
3+
:func:`sys.activate_stack_trampoline`, :func:`sys.deactivate_stack_trampoline`,
4+
and :func:`sys.is_stack_trampoline_active` APIs.
5+
Design by Pablo Galindo. Patch by Pablo Galindo and Christian Heimes
76
with contributions from Gregory P. Smith [Google] and Mark Shannon.

Python/clinic/sysmodule.c.h

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/sysmodule.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2059,12 +2059,12 @@ sys.activate_stack_trampoline
20592059
backend: str
20602060
/
20612061
2062-
Activate the perf profiler trampoline.
2062+
Activate stack profiler trampoline *backend*.
20632063
[clinic start generated code]*/
20642064

20652065
static PyObject *
20662066
sys_activate_stack_trampoline_impl(PyObject *module, const char *backend)
2067-
/*[clinic end generated code: output=5783cdeb51874b43 input=b09020e3a17c78c5]*/
2067+
/*[clinic end generated code: output=5783cdeb51874b43 input=a12df928758a82b4]*/
20682068
{
20692069
#ifdef PY_HAVE_PERF_TRAMPOLINE
20702070
if (strcmp(backend, "perf") == 0) {
@@ -2095,12 +2095,12 @@ sys_activate_stack_trampoline_impl(PyObject *module, const char *backend)
20952095
/*[clinic input]
20962096
sys.deactivate_stack_trampoline
20972097
2098-
Dectivate the perf profiler trampoline.
2098+
Dectivate stack profiler trampoline backend.
20992099
[clinic start generated code]*/
21002100

21012101
static PyObject *
21022102
sys_deactivate_stack_trampoline_impl(PyObject *module)
2103-
/*[clinic end generated code: output=b50da25465df0ef1 input=491f4fc1ed615736]*/
2103+
/*[clinic end generated code: output=b50da25465df0ef1 input=be0c9a8737fe7e8f]*/
21042104
{
21052105
if (_PyPerfTrampoline_Init(0) < 0) {
21062106
return NULL;
@@ -2111,12 +2111,12 @@ sys_deactivate_stack_trampoline_impl(PyObject *module)
21112111
/*[clinic input]
21122112
sys.is_stack_trampoline_active
21132113
2114-
Returns *True* if the perf profiler trampoline is active.
2114+
Return *True* if the stack profiler trampoline is active.
21152115
[clinic start generated code]*/
21162116

21172117
static PyObject *
21182118
sys_is_stack_trampoline_active_impl(PyObject *module)
2119-
/*[clinic end generated code: output=ab2746de0ad9d293 input=061fa5776ac9dd59]*/
2119+
/*[clinic end generated code: output=ab2746de0ad9d293 input=d802fd4a1afa2de8]*/
21202120
{
21212121
#ifdef PY_HAVE_PERF_TRAMPOLINE
21222122
if (_PyIsPerfTrampolineActive()) {

0 commit comments

Comments
 (0)