timerit 1.0.1__tar.gz → 1.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- timerit-1.2.0/MANIFEST.in +1 -0
- {timerit-1.0.1 → timerit-1.2.0}/PKG-INFO +156 -48
- timerit-1.0.1/timerit.egg-info/PKG-INFO → timerit-1.2.0/README.rst +128 -61
- timerit-1.2.0/pyproject.toml +135 -0
- timerit-1.2.0/requirements/docs.txt +8 -0
- timerit-1.2.0/requirements/optional.txt +2 -0
- timerit-1.2.0/requirements/tests.txt +3 -0
- timerit-1.2.0/tests/test_benchmarker.py +164 -0
- timerit-1.2.0/tests/test_import.py +2 -0
- timerit-1.2.0/tests/test_timerit.py +445 -0
- timerit-1.2.0/timerit/__init__.py +86 -0
- timerit-1.2.0/timerit/benchmarker.py +559 -0
- {timerit-1.0.1 → timerit-1.2.0}/timerit/core.py +149 -80
- timerit-1.2.0/timerit/py.typed +0 -0
- {timerit-1.0.1 → timerit-1.2.0}/timerit/relative.py +7 -7
- timerit-1.2.0/timerit.egg-info/PKG-INFO +353 -0
- {timerit-1.0.1 → timerit-1.2.0}/timerit.egg-info/SOURCES.txt +9 -3
- timerit-1.2.0/timerit.egg-info/requires.txt +23 -0
- timerit-1.0.1/README.rst +0 -212
- timerit-1.0.1/pyproject.toml +0 -34
- timerit-1.0.1/setup.py +0 -246
- timerit-1.0.1/timerit/__init__.py +0 -38
- timerit-1.0.1/timerit/core.pyi +0 -119
- timerit-1.0.1/timerit/relative.pyi +0 -32
- timerit-1.0.1/timerit.egg-info/requires.txt +0 -118
- {timerit-1.0.1 → timerit-1.2.0}/LICENSE +0 -0
- /timerit-1.0.1/timerit/py.typed → /timerit-1.2.0/requirements/runtime.txt +0 -0
- {timerit-1.0.1 → timerit-1.2.0}/setup.cfg +0 -0
- {timerit-1.0.1 → timerit-1.2.0}/timerit.egg-info/dependency_links.txt +0 -0
- {timerit-1.0.1 → timerit-1.2.0}/timerit.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
include requirements/*.txt
|
|
@@ -1,47 +1,64 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: timerit
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: A powerful multiline alternative to timeit
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
License: Apache 2
|
|
9
|
-
Platform: UNKNOWN
|
|
5
|
+
Author-email: Jon Crall <erotemic@gmail.com>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/Erotemic/timerit
|
|
10
8
|
Classifier: Development Status :: 5 - Production/Stable
|
|
11
9
|
Classifier: Intended Audience :: Developers
|
|
12
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
13
|
-
Classifier: Topic :: Utilities
|
|
14
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
19
10
|
Classifier: Programming Language :: Python :: 3.10
|
|
20
11
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
-
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Classifier: Topic :: Utilities
|
|
18
|
+
Requires-Python: >=3.10
|
|
22
19
|
Description-Content-Type: text/x-rst
|
|
20
|
+
License-File: LICENSE
|
|
23
21
|
Provides-Extra: all
|
|
24
|
-
|
|
22
|
+
Requires-Dist: pandas; extra == "all"
|
|
23
|
+
Requires-Dist: kwplot; extra == "all"
|
|
24
|
+
Provides-Extra: docs
|
|
25
|
+
Requires-Dist: sphinx>=5.0.1; extra == "docs"
|
|
26
|
+
Requires-Dist: sphinx-autobuild>=2021.3.14; extra == "docs"
|
|
27
|
+
Requires-Dist: sphinx_rtd_theme>=1.0.0; extra == "docs"
|
|
28
|
+
Requires-Dist: sphinxcontrib-napoleon>=0.7; extra == "docs"
|
|
29
|
+
Requires-Dist: sphinx-autoapi>=1.8.4; extra == "docs"
|
|
30
|
+
Requires-Dist: Pygments>=2.9.0; extra == "docs"
|
|
31
|
+
Requires-Dist: myst_parser>=0.18.0; extra == "docs"
|
|
32
|
+
Requires-Dist: sphinx-reredirects>=0.0.1; extra == "docs"
|
|
25
33
|
Provides-Extra: optional
|
|
26
|
-
|
|
27
|
-
|
|
34
|
+
Requires-Dist: pandas; extra == "optional"
|
|
35
|
+
Requires-Dist: kwplot; extra == "optional"
|
|
28
36
|
Provides-Extra: tests
|
|
29
|
-
|
|
30
|
-
|
|
37
|
+
Requires-Dist: xdoctest>=1.1.0; extra == "tests"
|
|
38
|
+
Requires-Dist: pytest>=6.2.5; extra == "tests"
|
|
39
|
+
Requires-Dist: pytest-cov>=3.0.0; extra == "tests"
|
|
40
|
+
Dynamic: license-file
|
|
31
41
|
|
|
32
42
|
|
|
33
|
-
|GithubActions| |Appveyor| |Codecov| |Pypi| |Downloads| |ReadTheDocs|
|
|
43
|
+
|GithubActions| |Appveyor| |Codecov| |Pypi| |Downloads| |ReadTheDocs|
|
|
34
44
|
|
|
35
|
-
.. .. |CircleCI|
|
|
36
45
|
|
|
37
46
|
Timerit
|
|
38
47
|
=======
|
|
39
48
|
|
|
40
|
-
A powerful multiline alternative to Python's builtin
|
|
49
|
+
A powerful multiline alternative to Python's builtin `timeit <https://docs.python.org/3/library/timeit.html>`_ module.
|
|
41
50
|
|
|
42
51
|
Docs are published at https://timerit.readthedocs.io/en/latest/ but this README
|
|
43
52
|
and code comments contain a walkthrough.
|
|
44
53
|
|
|
54
|
+
+---------------+--------------------------------------------+
|
|
55
|
+
| Github | https://github.com/Erotemic/timerit |
|
|
56
|
+
+---------------+--------------------------------------------+
|
|
57
|
+
| Pypi | https://pypi.org/project/timerit |
|
|
58
|
+
+---------------+--------------------------------------------+
|
|
59
|
+
| ReadTheDocs | https://timerit.readthedocs.io/en/latest/ |
|
|
60
|
+
+---------------+--------------------------------------------+
|
|
61
|
+
|
|
45
62
|
Description
|
|
46
63
|
-----------
|
|
47
64
|
|
|
@@ -52,36 +69,110 @@ convert to a single line.
|
|
|
52
69
|
Installation
|
|
53
70
|
------------
|
|
54
71
|
|
|
55
|
-
::
|
|
72
|
+
.. code:: bash
|
|
56
73
|
|
|
57
74
|
pip install timerit
|
|
58
75
|
|
|
59
76
|
|
|
60
|
-
|
|
61
|
-
|
|
77
|
+
Interactive Use
|
|
78
|
+
---------------
|
|
62
79
|
|
|
63
|
-
The
|
|
80
|
+
The ``timerit`` library provides a succinct API for interactive use:
|
|
64
81
|
|
|
65
82
|
.. code:: python
|
|
66
83
|
|
|
67
|
-
>>> import
|
|
68
|
-
>>>
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
84
|
+
>>> import timerit
|
|
85
|
+
>>> for _ in timerit:
|
|
86
|
+
... sum(range(100000))
|
|
87
|
+
Timed for: 288 loops, best of 5
|
|
88
|
+
time per loop: best=616.740 µs, mean=668.933 ± 124.2 µs
|
|
89
|
+
|
|
90
|
+
Compare to ``timeit``:
|
|
91
|
+
|
|
92
|
+
.. code:: bash
|
|
93
|
+
|
|
94
|
+
$ python -m timeit 'sum(range(100000))'
|
|
95
|
+
500 loops, best of 5: 721 usec per loop
|
|
96
|
+
|
|
97
|
+
By default, any code within the loop will be repeatedly executed until at least
|
|
98
|
+
200 ms have elapsed. The timing results are then printed out.
|
|
99
|
+
|
|
100
|
+
Here's what each of the numbers means:
|
|
74
101
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
102
|
+
- "288 loops": The code in the loop was run 288 times before the time limit was
|
|
103
|
+
reached.
|
|
104
|
+
|
|
105
|
+
- "best of 5": Consider only the fastest of every 5 measured times, when
|
|
106
|
+
calculating the mean and standard deviation. The reason for doing this is
|
|
107
|
+
that you can get slow times if the something in the background is consuming
|
|
108
|
+
resources, so you're generally only interested in the fastest times. This
|
|
109
|
+
idea is also described in the
|
|
110
|
+
`timeit docs <https://docs.python.org/3/library/timeit.html#timeit.Timer.repeat>`_.
|
|
111
|
+
|
|
112
|
+
- "best=616.740 µs": How long the fastest iteration took to run. For the reasons
|
|
113
|
+
described above, this is usually the most consistent number, and the primary
|
|
114
|
+
number you should focus on.
|
|
115
|
+
|
|
116
|
+
- "mean=668.933 ± 124.2 µs": The mean and the standard deviation of the "best of 5"
|
|
117
|
+
iterations. This statistic is usually not as robust or useful as the fastest
|
|
118
|
+
time, but sometimes its helpful to know if there's high variance.
|
|
119
|
+
|
|
120
|
+
The loop variable can be used as a context manager to only time a part of each
|
|
121
|
+
loop (e.g. to make the timings more accurate, or to incorporate a setup phase
|
|
122
|
+
that is not timed):
|
|
78
123
|
|
|
79
124
|
.. code:: python
|
|
80
125
|
|
|
81
|
-
>>>
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
126
|
+
>>> for timer in timerit:
|
|
127
|
+
... n = 100 * 1000
|
|
128
|
+
... with timer:
|
|
129
|
+
... sum(range(n))
|
|
130
|
+
Timed for: 318 loops, best of 5
|
|
131
|
+
time per loop: best=616.673 µs, mean=617.545 ± 0.9 µs
|
|
132
|
+
|
|
133
|
+
It is also possible to provide arguments controlling how the timing
|
|
134
|
+
measurements are made. See the online documentation for more information on
|
|
135
|
+
these arguments, but the snippet below runs for exactly 100 iterations, instead
|
|
136
|
+
of however many fit in 200 ms.
|
|
137
|
+
|
|
138
|
+
.. code:: python
|
|
139
|
+
|
|
140
|
+
>>> for _ in timerit(num=100):
|
|
141
|
+
... sum(range(100000))
|
|
142
|
+
Timed for: 100 loops, best of 5
|
|
143
|
+
time per loop: best=616.866 µs, mean=619.120 ± 5.3 µs
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
Automatic Import
|
|
147
|
+
~~~~~~~~~~~~~~~~
|
|
148
|
+
If you want to make ``timerit`` even easier to use interactively, you can move
|
|
149
|
+
the import to the PYTHONSTARTUP_ file. If defined, this environment variable
|
|
150
|
+
gives the path to a python script that will be executed just before every
|
|
151
|
+
interactive session. For example:
|
|
152
|
+
|
|
153
|
+
.. code:: bash
|
|
154
|
+
|
|
155
|
+
$ export PYTHONSTARTUP=~/.pythonrc
|
|
156
|
+
$ cat $PYTHONSTARTUP
|
|
157
|
+
import timerit
|
|
158
|
+
$ python
|
|
159
|
+
>>> for _ in timerit:
|
|
160
|
+
... sum(range(100000))
|
|
161
|
+
...
|
|
162
|
+
Timed for: 59 loops, best of 3
|
|
163
|
+
time per loop: best=2.532 ms, mean=3.309 ± 1.0 ms
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
Programmatic Use
|
|
167
|
+
----------------
|
|
168
|
+
|
|
169
|
+
The timerit library also provides a ``Timerit`` class that can be used
|
|
170
|
+
programmatically.
|
|
171
|
+
|
|
172
|
+
.. code:: python
|
|
173
|
+
|
|
174
|
+
>>> import math, timerit
|
|
175
|
+
>>> for timer in timerit:
|
|
85
176
|
>>> setup_vars = 10000
|
|
86
177
|
>>> with timer:
|
|
87
178
|
>>> math.factorial(setup_vars)
|
|
@@ -91,7 +182,13 @@ properties of the ``Timerit`` class to programmatically use results.
|
|
|
91
182
|
time per loop: best=2.064 ms, mean=2.115 ± 0.05 ms
|
|
92
183
|
t1.total_time = 0.4427177629695507
|
|
93
184
|
|
|
94
|
-
|
|
185
|
+
A common pattern is to create a single ``Timerit`` instance, then to repeatedly
|
|
186
|
+
"reset" it with different labels to test a number of different algorithms. The
|
|
187
|
+
labels assigned in this way will be incorporated into the report strings that
|
|
188
|
+
the ``Timerit`` instance produces. The "Benchmark Recipe" below shows an example
|
|
189
|
+
of this pattern. So do all of the scripts in the ``examples/`` directory.
|
|
190
|
+
|
|
191
|
+
There is also a simple one-liner that is comparable to ``timeit``'s IPython magic:
|
|
95
192
|
|
|
96
193
|
Compare the timeit version:
|
|
97
194
|
|
|
@@ -108,7 +205,7 @@ With the Timerit version:
|
|
|
108
205
|
Timed for: 1 loops, best of 1
|
|
109
206
|
time per loop: best=4.828 µs, mean=4.828 ± 0.0 µs
|
|
110
207
|
|
|
111
|
-
|
|
208
|
+
|
|
112
209
|
How it works
|
|
113
210
|
------------
|
|
114
211
|
|
|
@@ -134,7 +231,7 @@ Using the with statement inside the loop is nice because you can run untimed
|
|
|
134
231
|
setup code before you enter the context manager.
|
|
135
232
|
|
|
136
233
|
In the case where no setup code is required, a more concise version of the
|
|
137
|
-
|
|
234
|
+
syntax is available.
|
|
138
235
|
|
|
139
236
|
.. code:: python
|
|
140
237
|
|
|
@@ -218,9 +315,19 @@ Benchmark Recipe
|
|
|
218
315
|
# Your variables may change
|
|
219
316
|
ax = kwplot.figure(fnum=1, doclf=True).gca()
|
|
220
317
|
sns.lineplot(data=data, x='x', y='min', hue='method', marker='o', ax=ax)
|
|
221
|
-
ax.set_title('Benchmark')
|
|
222
|
-
ax.set_xlabel('
|
|
223
|
-
ax.set_ylabel('
|
|
318
|
+
ax.set_title('Benchmark Name')
|
|
319
|
+
ax.set_xlabel('x-variable description')
|
|
320
|
+
ax.set_ylabel('y-variable description')
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
Related Work
|
|
324
|
+
============
|
|
325
|
+
|
|
326
|
+
* `timeit <https://docs.python.org/3/library/timeit.html>`_: The builtin timeit module for profiling single statements.
|
|
327
|
+
|
|
328
|
+
* `line_profiler <https://github.com/pyutils/line_profiler>`_: Line-by-line profiling.
|
|
329
|
+
|
|
330
|
+
* `ubelt <https://github.com/Erotemic/ubelt>`_: This library was original developed as a component of ubelt, but has since become a standalone module.
|
|
224
331
|
|
|
225
332
|
|
|
226
333
|
.. |Travis| image:: https://img.shields.io/travis/Erotemic/timerit/master.svg?label=Travis%20CI
|
|
@@ -237,9 +344,10 @@ Benchmark Recipe
|
|
|
237
344
|
:target: https://circleci.com/gh/Erotemic/timerit
|
|
238
345
|
.. |ReadTheDocs| image:: https://readthedocs.org/projects/timerit/badge/?version=latest
|
|
239
346
|
:target: http://timerit.readthedocs.io/en/latest/
|
|
240
|
-
.. |CodeQuality| image:: https://api.codacy.com/project/badge/Grade/fdcedca723f24ec4be9c7067d91cb43b
|
|
347
|
+
.. |CodeQuality| image:: https://api.codacy.com/project/badge/Grade/fdcedca723f24ec4be9c7067d91cb43b
|
|
241
348
|
:target: https://www.codacy.com/manual/Erotemic/timerit?utm_source=github.com&utm_medium=referral&utm_content=Erotemic/timerit&utm_campaign=Badge_Grade
|
|
242
349
|
.. |GithubActions| image:: https://github.com/Erotemic/timerit/actions/workflows/tests.yml/badge.svg?branch=main
|
|
243
350
|
:target: https://github.com/Erotemic/timerit/actions?query=branch%3Amain
|
|
244
351
|
|
|
352
|
+
.. _PYTHONSTARTUP: https://docs.python.org/3/using/cmdline.html?highlight=pythonstartup#envvar-PYTHONSTARTUP
|
|
245
353
|
|
|
@@ -1,47 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
Summary: A powerful multiline alternative to timeit
|
|
5
|
-
Home-page: https://github.com/Erotemic/timerit
|
|
6
|
-
Author: Jon Crall
|
|
7
|
-
Author-email: erotemic@gmail.com
|
|
8
|
-
License: Apache 2
|
|
9
|
-
Platform: UNKNOWN
|
|
10
|
-
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
-
Classifier: Intended Audience :: Developers
|
|
12
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
13
|
-
Classifier: Topic :: Utilities
|
|
14
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
-
Requires-Python: >=3.6
|
|
22
|
-
Description-Content-Type: text/x-rst
|
|
23
|
-
Provides-Extra: all
|
|
24
|
-
Provides-Extra: all-strict
|
|
25
|
-
Provides-Extra: optional
|
|
26
|
-
Provides-Extra: optional-strict
|
|
27
|
-
Provides-Extra: runtime-strict
|
|
28
|
-
Provides-Extra: tests
|
|
29
|
-
Provides-Extra: tests-strict
|
|
30
|
-
License-File: LICENSE
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|GithubActions| |Appveyor| |Codecov| |Pypi| |Downloads| |ReadTheDocs|
|
|
34
|
-
|
|
35
|
-
.. .. |CircleCI|
|
|
1
|
+
|
|
2
|
+
|GithubActions| |Appveyor| |Codecov| |Pypi| |Downloads| |ReadTheDocs|
|
|
3
|
+
|
|
36
4
|
|
|
37
5
|
Timerit
|
|
38
6
|
=======
|
|
39
7
|
|
|
40
|
-
A powerful multiline alternative to Python's builtin
|
|
8
|
+
A powerful multiline alternative to Python's builtin `timeit <https://docs.python.org/3/library/timeit.html>`_ module.
|
|
41
9
|
|
|
42
10
|
Docs are published at https://timerit.readthedocs.io/en/latest/ but this README
|
|
43
11
|
and code comments contain a walkthrough.
|
|
44
12
|
|
|
13
|
+
+---------------+--------------------------------------------+
|
|
14
|
+
| Github | https://github.com/Erotemic/timerit |
|
|
15
|
+
+---------------+--------------------------------------------+
|
|
16
|
+
| Pypi | https://pypi.org/project/timerit |
|
|
17
|
+
+---------------+--------------------------------------------+
|
|
18
|
+
| ReadTheDocs | https://timerit.readthedocs.io/en/latest/ |
|
|
19
|
+
+---------------+--------------------------------------------+
|
|
20
|
+
|
|
45
21
|
Description
|
|
46
22
|
-----------
|
|
47
23
|
|
|
@@ -52,36 +28,110 @@ convert to a single line.
|
|
|
52
28
|
Installation
|
|
53
29
|
------------
|
|
54
30
|
|
|
55
|
-
::
|
|
31
|
+
.. code:: bash
|
|
56
32
|
|
|
57
33
|
pip install timerit
|
|
58
34
|
|
|
59
35
|
|
|
60
|
-
|
|
61
|
-
|
|
36
|
+
Interactive Use
|
|
37
|
+
---------------
|
|
62
38
|
|
|
63
|
-
The
|
|
39
|
+
The ``timerit`` library provides a succinct API for interactive use:
|
|
64
40
|
|
|
65
41
|
.. code:: python
|
|
66
42
|
|
|
67
|
-
>>> import
|
|
68
|
-
>>>
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
43
|
+
>>> import timerit
|
|
44
|
+
>>> for _ in timerit:
|
|
45
|
+
... sum(range(100000))
|
|
46
|
+
Timed for: 288 loops, best of 5
|
|
47
|
+
time per loop: best=616.740 µs, mean=668.933 ± 124.2 µs
|
|
48
|
+
|
|
49
|
+
Compare to ``timeit``:
|
|
50
|
+
|
|
51
|
+
.. code:: bash
|
|
74
52
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
53
|
+
$ python -m timeit 'sum(range(100000))'
|
|
54
|
+
500 loops, best of 5: 721 usec per loop
|
|
55
|
+
|
|
56
|
+
By default, any code within the loop will be repeatedly executed until at least
|
|
57
|
+
200 ms have elapsed. The timing results are then printed out.
|
|
58
|
+
|
|
59
|
+
Here's what each of the numbers means:
|
|
60
|
+
|
|
61
|
+
- "288 loops": The code in the loop was run 288 times before the time limit was
|
|
62
|
+
reached.
|
|
63
|
+
|
|
64
|
+
- "best of 5": Consider only the fastest of every 5 measured times, when
|
|
65
|
+
calculating the mean and standard deviation. The reason for doing this is
|
|
66
|
+
that you can get slow times if the something in the background is consuming
|
|
67
|
+
resources, so you're generally only interested in the fastest times. This
|
|
68
|
+
idea is also described in the
|
|
69
|
+
`timeit docs <https://docs.python.org/3/library/timeit.html#timeit.Timer.repeat>`_.
|
|
70
|
+
|
|
71
|
+
- "best=616.740 µs": How long the fastest iteration took to run. For the reasons
|
|
72
|
+
described above, this is usually the most consistent number, and the primary
|
|
73
|
+
number you should focus on.
|
|
74
|
+
|
|
75
|
+
- "mean=668.933 ± 124.2 µs": The mean and the standard deviation of the "best of 5"
|
|
76
|
+
iterations. This statistic is usually not as robust or useful as the fastest
|
|
77
|
+
time, but sometimes its helpful to know if there's high variance.
|
|
78
|
+
|
|
79
|
+
The loop variable can be used as a context manager to only time a part of each
|
|
80
|
+
loop (e.g. to make the timings more accurate, or to incorporate a setup phase
|
|
81
|
+
that is not timed):
|
|
78
82
|
|
|
79
83
|
.. code:: python
|
|
80
84
|
|
|
81
|
-
>>>
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
+
>>> for timer in timerit:
|
|
86
|
+
... n = 100 * 1000
|
|
87
|
+
... with timer:
|
|
88
|
+
... sum(range(n))
|
|
89
|
+
Timed for: 318 loops, best of 5
|
|
90
|
+
time per loop: best=616.673 µs, mean=617.545 ± 0.9 µs
|
|
91
|
+
|
|
92
|
+
It is also possible to provide arguments controlling how the timing
|
|
93
|
+
measurements are made. See the online documentation for more information on
|
|
94
|
+
these arguments, but the snippet below runs for exactly 100 iterations, instead
|
|
95
|
+
of however many fit in 200 ms.
|
|
96
|
+
|
|
97
|
+
.. code:: python
|
|
98
|
+
|
|
99
|
+
>>> for _ in timerit(num=100):
|
|
100
|
+
... sum(range(100000))
|
|
101
|
+
Timed for: 100 loops, best of 5
|
|
102
|
+
time per loop: best=616.866 µs, mean=619.120 ± 5.3 µs
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
Automatic Import
|
|
106
|
+
~~~~~~~~~~~~~~~~
|
|
107
|
+
If you want to make ``timerit`` even easier to use interactively, you can move
|
|
108
|
+
the import to the PYTHONSTARTUP_ file. If defined, this environment variable
|
|
109
|
+
gives the path to a python script that will be executed just before every
|
|
110
|
+
interactive session. For example:
|
|
111
|
+
|
|
112
|
+
.. code:: bash
|
|
113
|
+
|
|
114
|
+
$ export PYTHONSTARTUP=~/.pythonrc
|
|
115
|
+
$ cat $PYTHONSTARTUP
|
|
116
|
+
import timerit
|
|
117
|
+
$ python
|
|
118
|
+
>>> for _ in timerit:
|
|
119
|
+
... sum(range(100000))
|
|
120
|
+
...
|
|
121
|
+
Timed for: 59 loops, best of 3
|
|
122
|
+
time per loop: best=2.532 ms, mean=3.309 ± 1.0 ms
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
Programmatic Use
|
|
126
|
+
----------------
|
|
127
|
+
|
|
128
|
+
The timerit library also provides a ``Timerit`` class that can be used
|
|
129
|
+
programmatically.
|
|
130
|
+
|
|
131
|
+
.. code:: python
|
|
132
|
+
|
|
133
|
+
>>> import math, timerit
|
|
134
|
+
>>> for timer in timerit:
|
|
85
135
|
>>> setup_vars = 10000
|
|
86
136
|
>>> with timer:
|
|
87
137
|
>>> math.factorial(setup_vars)
|
|
@@ -91,7 +141,13 @@ properties of the ``Timerit`` class to programmatically use results.
|
|
|
91
141
|
time per loop: best=2.064 ms, mean=2.115 ± 0.05 ms
|
|
92
142
|
t1.total_time = 0.4427177629695507
|
|
93
143
|
|
|
94
|
-
|
|
144
|
+
A common pattern is to create a single ``Timerit`` instance, then to repeatedly
|
|
145
|
+
"reset" it with different labels to test a number of different algorithms. The
|
|
146
|
+
labels assigned in this way will be incorporated into the report strings that
|
|
147
|
+
the ``Timerit`` instance produces. The "Benchmark Recipe" below shows an example
|
|
148
|
+
of this pattern. So do all of the scripts in the ``examples/`` directory.
|
|
149
|
+
|
|
150
|
+
There is also a simple one-liner that is comparable to ``timeit``'s IPython magic:
|
|
95
151
|
|
|
96
152
|
Compare the timeit version:
|
|
97
153
|
|
|
@@ -108,7 +164,7 @@ With the Timerit version:
|
|
|
108
164
|
Timed for: 1 loops, best of 1
|
|
109
165
|
time per loop: best=4.828 µs, mean=4.828 ± 0.0 µs
|
|
110
166
|
|
|
111
|
-
|
|
167
|
+
|
|
112
168
|
How it works
|
|
113
169
|
------------
|
|
114
170
|
|
|
@@ -134,7 +190,7 @@ Using the with statement inside the loop is nice because you can run untimed
|
|
|
134
190
|
setup code before you enter the context manager.
|
|
135
191
|
|
|
136
192
|
In the case where no setup code is required, a more concise version of the
|
|
137
|
-
|
|
193
|
+
syntax is available.
|
|
138
194
|
|
|
139
195
|
.. code:: python
|
|
140
196
|
|
|
@@ -218,9 +274,19 @@ Benchmark Recipe
|
|
|
218
274
|
# Your variables may change
|
|
219
275
|
ax = kwplot.figure(fnum=1, doclf=True).gca()
|
|
220
276
|
sns.lineplot(data=data, x='x', y='min', hue='method', marker='o', ax=ax)
|
|
221
|
-
ax.set_title('Benchmark')
|
|
222
|
-
ax.set_xlabel('
|
|
223
|
-
ax.set_ylabel('
|
|
277
|
+
ax.set_title('Benchmark Name')
|
|
278
|
+
ax.set_xlabel('x-variable description')
|
|
279
|
+
ax.set_ylabel('y-variable description')
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
Related Work
|
|
283
|
+
============
|
|
284
|
+
|
|
285
|
+
* `timeit <https://docs.python.org/3/library/timeit.html>`_: The builtin timeit module for profiling single statements.
|
|
286
|
+
|
|
287
|
+
* `line_profiler <https://github.com/pyutils/line_profiler>`_: Line-by-line profiling.
|
|
288
|
+
|
|
289
|
+
* `ubelt <https://github.com/Erotemic/ubelt>`_: This library was original developed as a component of ubelt, but has since become a standalone module.
|
|
224
290
|
|
|
225
291
|
|
|
226
292
|
.. |Travis| image:: https://img.shields.io/travis/Erotemic/timerit/master.svg?label=Travis%20CI
|
|
@@ -237,9 +303,10 @@ Benchmark Recipe
|
|
|
237
303
|
:target: https://circleci.com/gh/Erotemic/timerit
|
|
238
304
|
.. |ReadTheDocs| image:: https://readthedocs.org/projects/timerit/badge/?version=latest
|
|
239
305
|
:target: http://timerit.readthedocs.io/en/latest/
|
|
240
|
-
.. |CodeQuality| image:: https://api.codacy.com/project/badge/Grade/fdcedca723f24ec4be9c7067d91cb43b
|
|
306
|
+
.. |CodeQuality| image:: https://api.codacy.com/project/badge/Grade/fdcedca723f24ec4be9c7067d91cb43b
|
|
241
307
|
:target: https://www.codacy.com/manual/Erotemic/timerit?utm_source=github.com&utm_medium=referral&utm_content=Erotemic/timerit&utm_campaign=Badge_Grade
|
|
242
308
|
.. |GithubActions| image:: https://github.com/Erotemic/timerit/actions/workflows/tests.yml/badge.svg?branch=main
|
|
243
309
|
:target: https://github.com/Erotemic/timerit/actions?query=branch%3Amain
|
|
244
310
|
|
|
311
|
+
.. _PYTHONSTARTUP: https://docs.python.org/3/using/cmdline.html?highlight=pythonstartup#envvar-PYTHONSTARTUP
|
|
245
312
|
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
build-backend = "setuptools.build_meta"
|
|
3
|
+
requires = [
|
|
4
|
+
"setuptools>=41.0.1",
|
|
5
|
+
"setuptools>=77",
|
|
6
|
+
]
|
|
7
|
+
|
|
8
|
+
[project]
|
|
9
|
+
name = "timerit"
|
|
10
|
+
description = "A powerful multiline alternative to timeit"
|
|
11
|
+
license = "Apache-2.0"
|
|
12
|
+
license-files = [
|
|
13
|
+
"LICENSE",
|
|
14
|
+
]
|
|
15
|
+
authors = [ { name = "Jon Crall", email = "erotemic@gmail.com" } ]
|
|
16
|
+
requires-python = ">=3.10"
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 5 - Production/Stable",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"Programming Language :: Python :: 3.10",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Programming Language :: Python :: 3.14",
|
|
25
|
+
"Programming Language :: Python :: 3.15",
|
|
26
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
27
|
+
"Topic :: Utilities",
|
|
28
|
+
]
|
|
29
|
+
dynamic = [
|
|
30
|
+
"dependencies",
|
|
31
|
+
"optional-dependencies",
|
|
32
|
+
"readme",
|
|
33
|
+
"version",
|
|
34
|
+
]
|
|
35
|
+
urls.Homepage = "https://github.com/Erotemic/timerit"
|
|
36
|
+
|
|
37
|
+
[tool.setuptools]
|
|
38
|
+
include-package-data = true
|
|
39
|
+
dynamic.dependencies.file = [
|
|
40
|
+
"requirements/runtime.txt",
|
|
41
|
+
]
|
|
42
|
+
dynamic.optional-dependencies.all.file = [
|
|
43
|
+
"requirements/optional.txt",
|
|
44
|
+
]
|
|
45
|
+
dynamic.optional-dependencies.docs.file = [
|
|
46
|
+
"requirements/docs.txt",
|
|
47
|
+
]
|
|
48
|
+
dynamic.optional-dependencies.optional.file = [
|
|
49
|
+
"requirements/optional.txt",
|
|
50
|
+
]
|
|
51
|
+
dynamic.optional-dependencies.tests.file = [
|
|
52
|
+
"requirements/tests.txt",
|
|
53
|
+
]
|
|
54
|
+
dynamic.readme.file = [
|
|
55
|
+
"README.rst",
|
|
56
|
+
]
|
|
57
|
+
dynamic.readme.content-type = "text/x-rst"
|
|
58
|
+
dynamic.version.attr = "timerit.__version__"
|
|
59
|
+
package-data."*" = [
|
|
60
|
+
"requirements/*.txt",
|
|
61
|
+
]
|
|
62
|
+
package-data.timerit = [
|
|
63
|
+
"py.typed",
|
|
64
|
+
]
|
|
65
|
+
packages.find.where = [
|
|
66
|
+
".",
|
|
67
|
+
]
|
|
68
|
+
packages.find.include = [
|
|
69
|
+
"timerit*",
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
[tool.mypy]
|
|
73
|
+
ignore_missing_imports = true
|
|
74
|
+
|
|
75
|
+
[tool.pytest]
|
|
76
|
+
ini_options.addopts = "-p no:doctest --xdoctest --xdoctest-style=google --ignore-glob=setup.py --ignore-glob=dev --ignore-glob=docs"
|
|
77
|
+
ini_options.norecursedirs = ".git ignore build __pycache__ dev _skbuild docs"
|
|
78
|
+
ini_options.filterwarnings = [
|
|
79
|
+
"default",
|
|
80
|
+
"ignore:.*No cfgstr given in Cacher constructor or call.*:Warning",
|
|
81
|
+
"ignore:.*Define the __nice__ method for.*:Warning",
|
|
82
|
+
"ignore:.*private pytest class or function.*:Warning",
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
[tool.coverage]
|
|
86
|
+
run.branch = true
|
|
87
|
+
report.exclude_lines = [
|
|
88
|
+
".* # nocover",
|
|
89
|
+
".* # pragma: no cover",
|
|
90
|
+
".*if six.PY2:",
|
|
91
|
+
"^ *pass *$",
|
|
92
|
+
"^ *raise",
|
|
93
|
+
"def __repr__",
|
|
94
|
+
"if __name__ == .__main__.:",
|
|
95
|
+
"if _debug:",
|
|
96
|
+
"if 0:",
|
|
97
|
+
"if trace is not None",
|
|
98
|
+
"pragma: no cover",
|
|
99
|
+
"raise AssertionError",
|
|
100
|
+
"raise NotImplementedError",
|
|
101
|
+
"verbose = .*",
|
|
102
|
+
]
|
|
103
|
+
report.omit = [
|
|
104
|
+
"*/setup.py",
|
|
105
|
+
"timerit/__main__.py",
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
[tool.xcookie]
|
|
109
|
+
tags = [
|
|
110
|
+
"erotemic",
|
|
111
|
+
"purepy",
|
|
112
|
+
"github",
|
|
113
|
+
]
|
|
114
|
+
mod_name = "timerit"
|
|
115
|
+
repo_name = "timerit"
|
|
116
|
+
rel_mod_parent_dpath = "."
|
|
117
|
+
os = [
|
|
118
|
+
"linux",
|
|
119
|
+
"osx",
|
|
120
|
+
"win",
|
|
121
|
+
]
|
|
122
|
+
min_python = "3.10"
|
|
123
|
+
version = "{mod_dpath}/__init__.py::__version__"
|
|
124
|
+
url = "https://github.com/Erotemic/timerit"
|
|
125
|
+
author = "Jon Crall"
|
|
126
|
+
author_email = "erotemic@gmail.com"
|
|
127
|
+
description = "A powerful multiline alternative to timeit"
|
|
128
|
+
license = "Apache 2"
|
|
129
|
+
dev_status = "stable"
|
|
130
|
+
typed = true
|
|
131
|
+
workspace_members = []
|
|
132
|
+
workspace_sync_versions = false
|
|
133
|
+
use_setup_py = false
|
|
134
|
+
use_pyproject_requirements = false
|
|
135
|
+
enable_gpg = true
|