pytest-codspeed 3.1.2__tar.gz → 3.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.
- {pytest_codspeed-3.1.2/src/pytest_codspeed.egg-info → pytest_codspeed-3.2.0}/PKG-INFO +1 -1
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/pyproject.toml +7 -1
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/src/pytest_codspeed/__init__.py +2 -2
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/src/pytest_codspeed/instruments/walltime.py +21 -13
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/src/pytest_codspeed/plugin.py +2 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0/src/pytest_codspeed.egg-info}/PKG-INFO +1 -1
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/LICENSE +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/README.md +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/setup.cfg +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/setup.py +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/src/pytest_codspeed/instruments/__init__.py +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/src/pytest_codspeed/instruments/valgrind/__init__.py +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/src/pytest_codspeed/instruments/valgrind/_wrapper/__init__.py +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/src/pytest_codspeed/instruments/valgrind/_wrapper/build.py +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/src/pytest_codspeed/instruments/valgrind/_wrapper/wrapper.c +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/src/pytest_codspeed/instruments/valgrind/_wrapper/wrapper.h +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/src/pytest_codspeed/instruments/valgrind/_wrapper/wrapper.pyi +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/src/pytest_codspeed/py.typed +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/src/pytest_codspeed/utils.py +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/src/pytest_codspeed.egg-info/SOURCES.txt +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/src/pytest_codspeed.egg-info/dependency_links.txt +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/src/pytest_codspeed.egg-info/entry_points.txt +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/src/pytest_codspeed.egg-info/requires.txt +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/src/pytest_codspeed.egg-info/top_level.txt +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/tests/test_pytest_plugin.py +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/tests/test_pytest_plugin_cpu_instrumentation.py +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/tests/test_pytest_plugin_walltime.py +0 -0
- {pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/tests/test_utils.py +0 -0
|
@@ -45,6 +45,12 @@ compat = [
|
|
|
45
45
|
]
|
|
46
46
|
test = ["pytest ~= 7.0", "pytest-cov ~= 4.0.0"]
|
|
47
47
|
|
|
48
|
+
[tool.uv.sources]
|
|
49
|
+
pytest-codspeed = { workspace = true }
|
|
50
|
+
|
|
51
|
+
[dependency-groups]
|
|
52
|
+
dev = ["pytest-codspeed"]
|
|
53
|
+
|
|
48
54
|
[project.entry-points]
|
|
49
55
|
pytest11 = { codspeed = "pytest_codspeed.plugin" }
|
|
50
56
|
|
|
@@ -60,7 +66,7 @@ version = { attr = "pytest_codspeed.__version__" }
|
|
|
60
66
|
|
|
61
67
|
|
|
62
68
|
[tool.bumpver]
|
|
63
|
-
current_version = "3.
|
|
69
|
+
current_version = "3.2.0"
|
|
64
70
|
version_pattern = "MAJOR.MINOR.PATCH[-TAG[NUM]]"
|
|
65
71
|
commit_message = "Release v{new_version} 🚀"
|
|
66
72
|
tag_message = "Release v{new_version} 🚀"
|
|
@@ -24,7 +24,10 @@ if TYPE_CHECKING:
|
|
|
24
24
|
DEFAULT_WARMUP_TIME_NS = 1_000_000_000
|
|
25
25
|
DEFAULT_MAX_TIME_NS = 3_000_000_000
|
|
26
26
|
TIMER_RESOLUTION_NS = get_clock_info("perf_counter").resolution * 1e9
|
|
27
|
-
DEFAULT_MIN_ROUND_TIME_NS = TIMER_RESOLUTION_NS *
|
|
27
|
+
DEFAULT_MIN_ROUND_TIME_NS = TIMER_RESOLUTION_NS * 1_000_000
|
|
28
|
+
|
|
29
|
+
IQR_OUTLIER_FACTOR = 1.5
|
|
30
|
+
STDEV_OUTLIER_FACTOR = 3
|
|
28
31
|
|
|
29
32
|
|
|
30
33
|
@dataclass
|
|
@@ -69,13 +72,14 @@ class BenchmarkStats:
|
|
|
69
72
|
@classmethod
|
|
70
73
|
def from_list(
|
|
71
74
|
cls,
|
|
72
|
-
|
|
75
|
+
times_per_round_ns: list[float],
|
|
73
76
|
*,
|
|
74
77
|
rounds: int,
|
|
75
78
|
iter_per_round: int,
|
|
76
79
|
warmup_iters: int,
|
|
77
80
|
total_time: float,
|
|
78
81
|
) -> BenchmarkStats:
|
|
82
|
+
times_ns = [t / iter_per_round for t in times_per_round_ns]
|
|
79
83
|
stdev_ns = stdev(times_ns) if len(times_ns) > 1 else 0
|
|
80
84
|
mean_ns = mean(times_ns)
|
|
81
85
|
if len(times_ns) > 1:
|
|
@@ -88,12 +92,16 @@ class BenchmarkStats:
|
|
|
88
92
|
)
|
|
89
93
|
iqr_ns = q3_ns - q1_ns
|
|
90
94
|
iqr_outlier_rounds = sum(
|
|
91
|
-
1
|
|
95
|
+
1
|
|
96
|
+
for t in times_ns
|
|
97
|
+
if t < q1_ns - IQR_OUTLIER_FACTOR * iqr_ns
|
|
98
|
+
or t > q3_ns + IQR_OUTLIER_FACTOR * iqr_ns
|
|
92
99
|
)
|
|
93
100
|
stdev_outlier_rounds = sum(
|
|
94
101
|
1
|
|
95
102
|
for t in times_ns
|
|
96
|
-
if t < mean_ns -
|
|
103
|
+
if t < mean_ns - STDEV_OUTLIER_FACTOR * stdev_ns
|
|
104
|
+
or t > mean_ns + STDEV_OUTLIER_FACTOR * stdev_ns
|
|
97
105
|
)
|
|
98
106
|
|
|
99
107
|
return cls(
|
|
@@ -129,20 +137,20 @@ def run_benchmark(
|
|
|
129
137
|
out = fn(*args, **kwargs)
|
|
130
138
|
|
|
131
139
|
# Warmup
|
|
132
|
-
|
|
140
|
+
times_per_round_ns: list[float] = []
|
|
133
141
|
warmup_start = start = perf_counter_ns()
|
|
134
142
|
while True:
|
|
135
143
|
start = perf_counter_ns()
|
|
136
144
|
fn(*args, **kwargs)
|
|
137
145
|
end = perf_counter_ns()
|
|
138
|
-
|
|
146
|
+
times_per_round_ns.append(end - start)
|
|
139
147
|
if end - warmup_start > config.warmup_time_ns:
|
|
140
148
|
break
|
|
141
149
|
|
|
142
150
|
# Round sizing
|
|
143
|
-
warmup_mean_ns = mean(
|
|
144
|
-
warmup_iters = len(
|
|
145
|
-
|
|
151
|
+
warmup_mean_ns = mean(times_per_round_ns)
|
|
152
|
+
warmup_iters = len(times_per_round_ns)
|
|
153
|
+
times_per_round_ns.clear()
|
|
146
154
|
iter_per_round = (
|
|
147
155
|
int(ceil(config.min_round_time_ns / warmup_mean_ns))
|
|
148
156
|
if warmup_mean_ns <= config.min_round_time_ns
|
|
@@ -163,7 +171,7 @@ def run_benchmark(
|
|
|
163
171
|
for _ in iter_range:
|
|
164
172
|
fn(*args, **kwargs)
|
|
165
173
|
end = perf_counter_ns()
|
|
166
|
-
|
|
174
|
+
times_per_round_ns.append(end - start)
|
|
167
175
|
|
|
168
176
|
if end - run_start > config.max_time_ns:
|
|
169
177
|
# TODO: log something
|
|
@@ -172,7 +180,7 @@ def run_benchmark(
|
|
|
172
180
|
total_time = (benchmark_end - run_start) / 1e9
|
|
173
181
|
|
|
174
182
|
stats = BenchmarkStats.from_list(
|
|
175
|
-
|
|
183
|
+
times_per_round_ns,
|
|
176
184
|
rounds=rounds,
|
|
177
185
|
total_time=total_time,
|
|
178
186
|
iter_per_round=iter_per_round,
|
|
@@ -240,12 +248,12 @@ class WallTimeInstrument(Instrument):
|
|
|
240
248
|
|
|
241
249
|
for bench in self.benchmarks:
|
|
242
250
|
rsd = bench.stats.stdev_ns / bench.stats.mean_ns
|
|
243
|
-
rsd_text = Text(f"{rsd*100:.1f}%")
|
|
251
|
+
rsd_text = Text(f"{rsd * 100:.1f}%")
|
|
244
252
|
if rsd > 0.1:
|
|
245
253
|
rsd_text.stylize("red bold")
|
|
246
254
|
table.add_row(
|
|
247
255
|
escape(bench.name),
|
|
248
|
-
f"{bench.stats.min_ns/bench.stats.iter_per_round:,.0f}ns",
|
|
256
|
+
f"{bench.stats.min_ns / bench.stats.iter_per_round:,.0f}ns",
|
|
249
257
|
rsd_text,
|
|
250
258
|
f"{bench.stats.total_time:,.2f}s",
|
|
251
259
|
f"{bench.stats.iter_per_round * bench.stats.rounds:,}",
|
|
@@ -5,6 +5,7 @@ import gc
|
|
|
5
5
|
import importlib.util
|
|
6
6
|
import json
|
|
7
7
|
import os
|
|
8
|
+
import random
|
|
8
9
|
from dataclasses import dataclass, field
|
|
9
10
|
from pathlib import Path
|
|
10
11
|
from time import time
|
|
@@ -259,6 +260,7 @@ def _measure(
|
|
|
259
260
|
*args: P.args,
|
|
260
261
|
**kwargs: P.kwargs,
|
|
261
262
|
) -> T:
|
|
263
|
+
random.seed(0)
|
|
262
264
|
is_gc_enabled = gc.isenabled()
|
|
263
265
|
if is_gc_enabled:
|
|
264
266
|
gc.collect()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/src/pytest_codspeed/instruments/valgrind/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/src/pytest_codspeed.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/src/pytest_codspeed.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytest_codspeed-3.1.2 → pytest_codspeed-3.2.0}/tests/test_pytest_plugin_cpu_instrumentation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|