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.
|