Skip to content

Commit b1f5fad

Browse files
Евгений БлиновЕвгений Блинов
authored andcommitted
Fix histogram
1 parent 57d88cc commit b1f5fad

5 files changed

Lines changed: 22 additions & 8 deletions

File tree

microbenchmark/__main__.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,10 @@
33
import importlib
44
import sys
55
from pathlib import Path
6-
from typing import Union
76

87
from microbenchmark.scenario import Scenario
98
from microbenchmark.scenario_group import ScenarioGroup
109

11-
_Target = Union[Scenario, ScenarioGroup]
12-
1310

1411
def main(argv: list[str] | None = None) -> None:
1512
args = argv if argv is not None else sys.argv[1:]

microbenchmark/_render.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,12 @@ def histogram_bounds(durations: Sequence[float]) -> tuple[float, float]:
9898
9999
Args:
100100
durations: Sequence of per-call timings in seconds.
101+
102+
Raises:
103+
ValueError: If *durations* is empty.
101104
"""
105+
if not durations:
106+
raise ValueError('durations must not be empty')
102107
sorted_durs = sorted(durations)
103108
lo = sorted_durs[0]
104109
p99_idx = min(len(sorted_durs) - 1, int(len(sorted_durs) * 0.99))

microbenchmark/scenario.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,7 @@ def _call_once(self) -> None:
6868
def run(self, warmup: int = 0) -> BenchmarkResult:
6969
timer = self._timer
7070
for _ in range(max(warmup, 0)):
71-
timer()
7271
self._call_once()
73-
timer()
7472
durations: list[float] = []
7573
loop_start = timer()
7674
for _ in range(self.number):
@@ -160,7 +158,8 @@ def _fn_call_str(function: object, arguments: Arguments | None) -> str:
160158

161159
def _render_result(result: BenchmarkResult) -> list[str]:
162160
scenario = result.scenario
163-
assert scenario is not None
161+
if scenario is None:
162+
raise ValueError('BenchmarkResult.scenario must not be None for rendering')
164163
call_str = _fn_call_str(scenario.function, scenario._arguments)
165164
label_width = len('p95 mean:')
166165
lines: list[str] = []

tests/units/test_render.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import sys
77
import textwrap
88

9+
import pytest
10+
911
from microbenchmark._render import (
1012
draw_box,
1113
draw_histogram,
@@ -292,6 +294,11 @@ def test_histogram_bounds_single_value():
292294
assert lo == hi == 0.005
293295

294296

297+
def test_histogram_bounds_empty_raises():
298+
with pytest.raises(ValueError, match='empty'):
299+
histogram_bounds([])
300+
301+
295302
# ---------------------------------------------------------------------------
296303
# draw_histogram_axis
297304
# ---------------------------------------------------------------------------

tests/units/test_scenario.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from sigmatch import SignatureMismatchError
1010

1111
from microbenchmark import BenchmarkResult, Scenario, ScenarioGroup, arguments
12-
from microbenchmark.scenario import _fn_call_str
12+
from microbenchmark.scenario import _fn_call_str, _render_result
1313

1414
# ---------------------------------------------------------------------------
1515
# Construction
@@ -354,7 +354,7 @@ def fake_timer() -> float:
354354
scenario = Scenario(lambda: None, name='s', number=3, timer=fake_timer)
355355
result = scenario.run(warmup=2)
356356

357-
assert tick[0] == 12 # warmup: 2*2=4, loop_start: 1, run: 3*2=6, loop_end: 1 → 12
357+
assert tick[0] == 8 # loop_start: 1, run: 3*2=6, loop_end: 1 → 8 (warmup has no timer calls)
358358
assert len(result.durations) == 3
359359
assert result.durations == pytest.approx((1.0, 1.0, 1.0))
360360

@@ -603,3 +603,9 @@ def test_fn_call_str_non_oserror_propagates():
603603

604604
with pytest.raises(ValueError, match='unexpected'), patch('microbenchmark.scenario.superrepr', side_effect=ValueError('unexpected')):
605605
_fn_call_str(fn, None)
606+
607+
608+
def test_render_result_raises_when_scenario_is_none():
609+
result = BenchmarkResult.from_json('{"durations":[0.001,0.002],"is_primary":true,"scenario":null}')
610+
with pytest.raises(ValueError, match='scenario must not be None'):
611+
_render_result(result)

0 commit comments

Comments
 (0)