File: __init__.py

package info (click to toggle)
python-line-profiler 5.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,256 kB
  • sloc: python: 8,119; sh: 810; ansic: 297; makefile: 14
file content (264 lines) | stat: -rw-r--r-- 8,514 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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
"""
Line Profiler
=============

The line_profiler module for doing line-by-line profiling of functions

+---------------+--------------------------------------------+
| Github        | https://github.com/pyutils/line_profiler   |
+---------------+--------------------------------------------+
| Pypi          | https://pypi.org/project/line_profiler     |
+---------------+--------------------------------------------+
| ReadTheDocs   | https://kernprof.readthedocs.io/en/latest/ |
+---------------+--------------------------------------------+


Installation
============

Releases of :py:mod:`line_profiler` and :py:mod:`kernprof` can be installed
using pip

.. code:: bash

    pip install line_profiler


The package also provides extras for optional dependencies, which can be
installed via:


.. code:: bash

    pip install line_profiler[all]


.. _line-profiler-basic-usage:

Line Profiler Basic Usage
=========================

To demonstrate line profiling, we first need to generate a Python script to
profile. Write the following code to a file called :file:`demo_primes.py`:

.. code:: python

    from line_profiler import profile


    @profile
    def is_prime(n):
        '''
        Check if the number "n" is prime, with n > 1.

        Returns a boolean, True if n is prime.
        '''
        max_val = n ** 0.5
        stop = int(max_val + 1)
        for i in range(2, stop):
            if n % i == 0:
                return False
        return True


    @profile
    def find_primes(size):
        primes = []
        for n in range(size):
            flag = is_prime(n)
            if flag:
                primes.append(n)
        return primes


    @profile
    def main():
        print('start calculating')
        primes = find_primes(100000)
        print(f'done calculating. Found {len(primes)} primes.')


    if __name__ == '__main__':
        main()


In this script we explicitly import the
:py:deco:`profile <line_profiler.explicit_profiler.GlobalProfiler>` function
from :py:mod:`line_profiler`, and then we decorate function of interest with
:py:deco:`profile`.

By default nothing is profiled when running the script.

.. code:: bash

    python demo_primes.py


The output will be

.. code::

    start calculating
    done calculating. Found 9594 primes.


The quickest way to enable profiling is to set the environment variable
:envvar:`LINE_PROFILE=1 <LINE_PROFILE>` and running your script as normal.

.. .. todo: add a link that points to docs showing all the different ways to
.. .. to enable profiling.

.. code:: bash

    LINE_PROFILE=1 python demo_primes.py

This will output 3 files: :file:`profile_output.txt`,
:file:`profile_output_<timestamp>.txt`, and :file:`profile_output.lprof`; and
:file:`stdout` will look something like:


.. code::

    start calculating
    done calculating. Found 9594 primes.
    Timer unit: 1e-09 s

      0.65 seconds - demo_primes.py:4 - is_prime
      1.47 seconds - demo_primes.py:19 - find_primes
      1.51 seconds - demo_primes.py:29 - main
    Wrote profile results to profile_output.txt
    Wrote profile results to profile_output_2023-08-12T193302.txt
    Wrote profile results to profile_output.lprof
    To view details run:
    python -m line_profiler -rtmz profile_output.lprof


The details contained in the output txt files or by running the script provided
in the output will show detailed line-by-line timing information for each
decorated function.


.. code::

    Timer unit: 1e-06 s

    Total time: 0.731624 s
    File: ./demo_primes.py
    Function: is_prime at line 4

    Line #      Hits         Time  Per Hit   % Time  Line Contents
    ==============================================================
         4                                           @profile
         5                                           def is_prime(n):
         6                                               '''
         7                                               Check if the number "n" is prime, with n > 1.
         8
         9                                               Returns a boolean, True if n is prime.
        10                                               '''
        11    100000      14178.0      0.1      1.9      max_val = n ** 0.5
        12    100000      22830.7      0.2      3.1      stop = int(max_val + 1)
        13   2755287     313514.1      0.1     42.9      for i in range(2, stop):
        14   2745693     368716.6      0.1     50.4          if n % i == 0:
        15     90406      11462.9      0.1      1.6              return False
        16      9594        922.0      0.1      0.1      return True


    Total time: 1.56771 s
    File: ./demo_primes.py
    Function: find_primes at line 19

    Line #      Hits         Time  Per Hit   % Time  Line Contents
    ==============================================================
        19                                           @profile
        20                                           def find_primes(size):
        21         1          0.2      0.2      0.0      primes = []
        22    100001      10280.4      0.1      0.7      for n in range(size):
        23    100000    1544196.6     15.4     98.5          flag = is_prime(n)
        24    100000      11375.4      0.1      0.7          if flag:
        25      9594       1853.2      0.2      0.1              primes.append(n)
        26         1          0.1      0.1      0.0      return primes


    Total time: 1.60483 s
    File: ./demo_primes.py
    Function: main at line 29

    Line #      Hits         Time  Per Hit   % Time  Line Contents
    ==============================================================
        29                                           @profile
        30                                           def main():
        31         1         14.0     14.0      0.0      print('start calculating')
        32         1    1604795.1    2e+06    100.0      primes = find_primes(100000)
        33         1         20.6     20.6      0.0      print(f'done calculating. Found {len(primes)} primes.')


See Also:

    * autoprofiling usage in: :py:mod:`line_profiler.autoprofile`

Limitations
===========

Line profiling does have limitations, and it is important to be aware of them.
Profiling multi-threaded, multi-processing, and asynchronous code may produce
unexpected or no results. All profiling also adds some amount of overhead to
the runtime, which may influence which parts of the code become bottlenecks.

Line profiler only measures the time between the start and end of a Python
call, so for benchmarking GPU code (e.g. with torch), which have asynchronous
or delayed behavior, it will only show the time to sync blocking calls in the
main thread.

Other profilers have different limitations and different trade-offs. It's good
to be aware of the right tool for the job. Here is a short list of other
profiling tools:


* `Scalene <https://github.com/plasma-umass/scalene>`_: A CPU+GPU+memory sampling based profiler.

* `PyInstrument  <https://github.com/joerick/pyinstrument>`_: A call stack profiler.

* `Yappi <https://github.com/sumerc/yappi>`_: A tracing profiler that is multithreading, asyncio and gevent aware.

* `profile / cProfile <https://docs.python.org/3/library/profile.html>`_: The builtin profile module.

* `timeit <https://docs.python.org/3/library/timeit.html>`_: The builtin timeit module for profiling single statements.

* `timerit <https://github.com/Erotemic/timerit>`_: A multi-statements alternative to the builtin :py:mod:`timeit` module.

* `torch.profiler <https://pytorch.org/docs/stable/profiler.html>`_ tools for profiling torch code.


.. .. todo: give more details on exact limitations.

"""
# Note: there are better ways to generate primes
# https://github.com/Sylhare/nprime

__submodules__ = [
    'line_profiler',
    'ipython_extension',
]

__autogen__ = """
mkinit ./line_profiler/__init__.py --relative
mkinit ./line_profiler/__init__.py --relative -w
"""


# from .line_profiler import __version__

# NOTE: This needs to be in sync with ../kernprof.py and line_profiler.py
__version__ = '5.0.0'

from .line_profiler import (LineProfiler,
                            load_ipython_extension, load_stats, main,
                            show_func, show_text,)


from .explicit_profiler import profile


__all__ = ['LineProfiler', 'line_profiler',
           'load_ipython_extension', 'load_stats', 'main', 'show_func',
           'show_text', '__version__', 'profile']