File: reference.md

package info (click to toggle)
python-pyinstrument 5.1.1%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,624 kB
  • sloc: python: 6,713; ansic: 897; makefile: 46; sh: 26; javascript: 18
file content (139 lines) | stat: -rw-r--r-- 4,059 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# API Reference

## Command line interface

``pyinstrument`` works just like ``python``, on the command line, so you can
call your scripts like ``pyinstrument script.py`` or ``pyinstrument -m
my_module``.

When your script ends, or when you kill it with `ctrl-c`, pyinstrument will
print a profile report to the console.

```{program-output} pyinstrument --help
```

## Python API

The Python API is also available, for calling pyinstrument directly from
Python and writing integrations with with other tools.

### The `profile` function

For example:

```python
with pyinstrument.profile():
    time.sleep(1)
```

This will print something like:

```
pyinstrument ........................................
.
.  Block at testfile.py:2
.
.  1.000 <module>  testfile.py:1
.  └─ 1.000 sleep  <built-in>
.
.....................................................
```

You can also use it as a function/method decorator, like this:

```python
@pyinstrument.profile()
def my_function():
    time.sleep(1)
```

```{eval-rst}
.. function:: pyinstrument.profile(*, interval=0.001, async_mode="disabled", \
                                 use_timing_thread=None, renderer=None, \
                                 target_description=None)

    Creates a context-manager or function decorator object, which profiles the given code and prints the output to stdout.

    The *interval*, *async_mode* and *use_timing_thread* parameters are passed through to the underlying :class:`pyinstrument.Profiler` object.

    You can pass a renderer to customise the output. By default, it uses a :class:`ConsoleRenderer <pyinstrument.renderers.ConsoleRenderer>` with `short_mode` set.

```

### The Profiler object

```{eval-rst}
.. autoclass:: pyinstrument.Profiler
    :members:
    :special-members: __enter__
```

### Sessions

```{eval-rst}
.. autoclass:: pyinstrument.session.Session
    :members:
```

### Renderers

Renderers transform a tree of {class}`Frame` objects into some form of output.

Rendering has two steps:

1. First, the renderer will 'preprocess' the Frame tree, applying each processor in the ``processor`` property, in turn.
2. The resulting tree is rendered into the desired format.

Therefore, rendering can be customised by changing the ``processors`` property. For example, you can disable time-aggregation (making the profile into a timeline) by removing {func}`aggregate_repeated_calls`.

```{eval-rst}
.. autoclass:: pyinstrument.renderers.FrameRenderer
    :members:

.. autoclass:: pyinstrument.renderers.ConsoleRenderer

.. autoclass:: pyinstrument.renderers.HTMLRenderer

.. autoclass:: pyinstrument.renderers.JSONRenderer

.. autoclass:: pyinstrument.renderers.SpeedscopeRenderer
```

### Processors

```{eval-rst}
.. automodule:: pyinstrument.processors
    :members:
```

### Internals notes

Frames are recorded by the Profiler in a time-linear fashion. While profiling,
the profiler builds a list of frame stacks, with the frames having in format:

    function_name <null> filename <null> function_line_number

When profiling is complete, this list is turned into a tree structure of
Frame objects. This tree contains all the information as gathered by the
profiler, suitable for a flame render.

#### Frame objects, the call tree, and processors

The frames are assembled to a call tree by the profiler session. The
time-linearity is retained at this stage.

Before rendering, the call tree is then fed through a sequence of 'processors'
to transform the tree for output.

The most interesting is `aggregate_repeated_calls`, which combines different
instances of function calls into the same frame. This is intuitive as a
summary of where time was spent during execution.

The rest of the processors focus on removing or hiding irrelevant Frames
from the output.

#### Self time frames vs. frame.self_time

Self time nodes exist to record time spent in a node, but not in its children.
But normal frame objects can have self_time too. Why? frame.self_time is used
to store the self_time of any nodes that were removed during processing.