最近は Python のテストフレームワークとして pytest がデファクトになりつつある。
今回は、そんな pytest のプラグインの一つである pytest-benchmark を使ってベンチマークテストを書いてみることにする。
ここで、ベンチマークテストというのはプログラムの特定部位のパフォーマンスを計測するためのテストを指す。
ベンチマークテストを使うことで、チューニングの成果を定量的に把握したり、加えた変更によって別の場所で性能がデグレードしていないかを確かめることができる。
なお、チューニングする前のボトルネック探しについては別途プロファイラを使うのが良いと思う。
blog.amedama.jp
blog.amedama.jp
使った環境は次の通り。
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.14.4
BuildVersion: 18E226
$ python -V
Python 3.7.3
下準備
まずはパッケージをインストールしておく。
$ pip install pytest-benchmark
まずは試してみる
すごく単純なベンチマークテストを書いて動きを確認してみよう。
一般的に pytest を使うときはプロジェクトのルートに tests
というディレクトリを用意することが多い。
$ mkdir -p tests
そして、作成したディレクトリに test_
から始まるテストコードを記述したファイルを用意する。
以下のサンプルコードでは test_example.py
という名前でベンチマークテストのファイルを用意している。
サンプルコードの中では something()
という関数を仮想的なベンチマーク対象としている。
テスト自体は test_
から始まる関数として記述することが一般的で test_something_benchmark()
という名前で定義している。
pytest-benchmark を使ったベンチマークテストでは引数に benchmark
を指定すると、必要なオブジェクトがインジェクトされる。
$ cat << 'EOF' > tests/test_example.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time
import pytest
def something(duration=0.1):
"""ベンチマークしたい対象"""
time.sleep(duration)
return True
def test_something_benchmark(benchmark):
"""ベンチマークを実施するテスト
:param benchmark: pytest-benchmark がインジェクトするフィクスチャ
"""
# テスト対象を引数として benchmark を実行する
ret = benchmark(something)
# 返り値を検証する
assert ret
if __name__ == '__main__':
pytest.main(['-v', __file__])
EOF
あまり説明が長くなっても何なので実際に動かしてみよう。
実行は通常通りテストランナーである pytest
コマンドを起動するだけ。
$ pytest
=========================================================== test session starts ============================================================
platform darwin -- Python 3.7.3, pytest-4.4.1, py-1.8.0, pluggy-0.11.0
benchmark: 3.2.2 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /Users/amedama/Documents/temporary/pybench
plugins: benchmark-3.2.2
collected 1 item
tests/test_example.py . [100%]
--------------------------------------------------- benchmark: 1 tests --------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
-------------------------------------------------------------------------------------------------------------------------
test_something_benchmark 100.2115 105.2357 102.0071 1.9180 101.5772 2.3150 2;0 9.8032 10 1
-------------------------------------------------------------------------------------------------------------------------
Legend:
Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile.
OPS: Operations Per Second, computed as 1 / Mean
========================================================= 1 passed in 2.28 seconds =========================================================
見慣れた表示の中にベンチマークの結果として実行にかかった時間に関する統計量が表示されている。
表示からは、概ね一回の実行に 100ms 前後かかっていることが分かる。
これはテスト対象の something()
がデフォルトで 100ms のスリープを入れることから直感にも則している。
実行回数などを制御する
先ほどは 1 回の試行 (iteration) でテスト対象 10 回の呼び出し (rounds) をしていた。
上記の回数を変更したいときは、次のように benchmark#pedantic()
関数を使う。
import time
import pytest
def something(duration=0.1):
time.sleep(duration)
return True
def test_something_benchmark(benchmark):
ret = benchmark.pedantic(something,
kwargs={'duration': 0.0001},
rounds=100,
iterations=10)
assert ret
if __name__ == '__main__':
pytest.main(['-v', __file__])
上記を実行してみよう。
今度は 10 回の試行 (iteration) で各 100 回の呼び出し (rounds) になった。
なお、スリープする時間を短くしたにも関わらず数字が変わっていないように見えるが、単位がミリ秒からマイクロ秒に変化している。
$ pytest
=========================================================== test session starts ============================================================
platform darwin -- Python 3.7.3, pytest-4.4.1, py-1.8.0, pluggy-0.11.0
benchmark: 3.2.2 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /Users/amedama/Documents/temporary/pybench
plugins: benchmark-3.2.2
collected 1 item
tests/test_example.py . [100%]
------------------------------------------------------ benchmark: 1 tests ------------------------------------------------------
Name (time in us) Min Max Mean StdDev Median IQR Outliers OPS (Kops/s) Rounds Iterations
--------------------------------------------------------------------------------------------------------------------------------
test_something_benchmark 134.3719 266.8602 143.7150 15.9095 138.1588 8.6015 6;7 6.9582 100 10
--------------------------------------------------------------------------------------------------------------------------------
Legend:
Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile.
OPS: Operations Per Second, computed as 1 / Mean
========================================================= 1 passed in 0.19 seconds =========================================================
ベンチマークだけ実行する・スキップする
一般的に、ベンチマークテストは実行に時間がかかるものが多い。
通常のユニットテストと混ぜて実行してしまうと、全体のかかる時間が伸びて使い勝手が悪くなる恐れがある。
そうした場合のために pytest-benchmark はベンチマークテストだけ実行したりスキップしたりできる。
次のサンプルコードでは通常のユニットテストとベンチマークテストが混在している。
import time
import pytest
def something(duration=0.1):
time.sleep(duration)
return True
def test_something():
"""通常のテスト"""
ret = something()
assert ret
def test_something_benchmark(benchmark):
"""ベンチマークテスト"""
ret = benchmark(something)
assert ret
if __name__ == '__main__':
pytest.main(['-v', __file__])
こうした状況下で、もしベンチマークテストを実行したくないときは --benchmark-skip
オプションを指定してテストランナーを走らせよう。
$ pytest --benchmark-skip
=========================================================== test session starts ============================================================
platform darwin -- Python 3.7.3, pytest-4.4.1, py-1.8.0, pluggy-0.11.0
benchmark: 3.2.2 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /Users/amedama/Documents/temporary/pybench
plugins: benchmark-3.2.2
collected 2 items
tests/test_example.py .s [100%]
=================================================== 1 passed, 1 skipped in 0.14 seconds ====================================================
ベンチマークテストがスキップされていることが分かる。
反対に、ベンチマークテストだけ実行したいときは、次のように --benchmark-only
オプションを指定する。
$ pytest --benchmark-only
=========================================================== test session starts ============================================================
platform darwin -- Python 3.7.3, pytest-4.4.1, py-1.8.0, pluggy-0.11.0
benchmark: 3.2.2 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /Users/amedama/Documents/temporary/pybench
plugins: benchmark-3.2.2
collected 2 items
tests/test_example.py s. [100%]
--------------------------------------------------- benchmark: 1 tests --------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
-------------------------------------------------------------------------------------------------------------------------
test_something_benchmark 100.0697 105.2460 103.0371 2.1262 102.9510 4.5859 7;0 9.7052 10 1
-------------------------------------------------------------------------------------------------------------------------
Legend:
Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile.
OPS: Operations Per Second, computed as 1 / Mean
=================================================== 1 passed, 1 skipped in 2.26 seconds ====================================================
特定のベンチマークだけ実行したい
前述した通りベンチマークテストは実行に時間がかかることが多い。
プロジェクトに数多くベンチマークテストがあるとピンポイントで走らせたくなることが多い。
例えば次のサンプルコードには二つの実行時間が異なるテストが書かれている。
import time
import pytest
def something(duration=0.1):
time.sleep(duration)
return True
def test_something_benchmark_quick(benchmark):
ret = benchmark(something, duration=0.01)
assert ret
def test_something_benchmark_slow(benchmark):
ret = benchmark(something, duration=1.0)
assert ret
if __name__ == '__main__':
pytest.main(['-v', __file__])
上記のような状況で、毎回どちらも実行していては時間を浪費してしまう。
$ pytest
=========================================================== test session starts ============================================================
platform darwin -- Python 3.7.3, pytest-4.4.1, py-1.8.0, pluggy-0.11.0
benchmark: 3.2.2 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /Users/amedama/Documents/temporary/pybench
plugins: benchmark-3.2.2
collected 2 items
tests/test_example.py .. [100%]
--------------------------------------------------------------------------------------------- benchmark: 2 tests ---------------------------------------------------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_something_benchmark_quick 10.0496 (1.0) 12.7429 (1.0) 11.7022 (1.0) 0.9845 (1.0) 11.8118 (1.0) 1.8297 (1.0) 27;0 85.4542 (1.0) 79 1
test_something_benchmark_slow 1,000.7044 (99.58) 1,005.1836 (78.88) 1,002.3219 (85.65) 1.9021 (1.93) 1,001.7429 (84.81) 2.9902 (1.63) 1;0 0.9977 (0.01) 5 1
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Legend:
Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile.
OPS: Operations Per Second, computed as 1 / Mean
========================================================= 2 passed in 9.03 seconds =========================================================
ピンポイントでテストを実行したいときは pytest の基本的な機能を使えば良い。
例えば、ファイル名やテストの関数名を元に実行する対象を絞りたいときは pytest
コマンドで -k
オプションを指定する。
$ pytest -k test_something_benchmark_quick
=========================================================== test session starts ============================================================
platform darwin -- Python 3.7.3, pytest-4.4.1, py-1.8.0, pluggy-0.11.0
benchmark: 3.2.2 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /Users/amedama/Documents/temporary/pybench
plugins: benchmark-3.2.2
collected 2 items / 1 deselected / 1 selected
tests/test_example.py . [100%]
---------------------------------------------------- benchmark: 1 tests ----------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
----------------------------------------------------------------------------------------------------------------------------
test_something_benchmark_quick 10.0454 12.7581 11.8572 0.9654 12.5086 1.6299 20;0 84.3367 90 1
----------------------------------------------------------------------------------------------------------------------------
Legend:
Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile.
OPS: Operations Per Second, computed as 1 / Mean
================================================== 1 passed, 1 deselected in 2.12 seconds ==================================================
あるいは、次のように実行するモジュールとテスト名を指定する。
$ pytest tests/test_example.py::test_something_benchmark_quick
=========================================================== test session starts ============================================================
platform darwin -- Python 3.7.3, pytest-4.4.1, py-1.8.0, pluggy-0.11.0
benchmark: 3.2.2 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /Users/amedama/Documents/temporary/pybench
plugins: benchmark-3.2.2
collected 1 item
tests/test_example.py . [100%]
---------------------------------------------------- benchmark: 1 tests ----------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
----------------------------------------------------------------------------------------------------------------------------
test_something_benchmark_quick 10.0478 12.7498 11.6334 1.0232 11.6050 2.0731 57;0 85.9594 91 1
----------------------------------------------------------------------------------------------------------------------------
Legend:
Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile.
OPS: Operations Per Second, computed as 1 / Mean
========================================================= 1 passed in 2.11 seconds =========================================================
デフォルトではベンチマークテストが実行されないようにする
なお、オプションを毎回指定するのが面倒なときは pytest の設定ファイルを用意しておくと良い。
例えば次のように pytest.ini
を用意しておくとデフォルトではベンチマークテストが実行されなくなる。
$ cat << 'EOF' > pytest.ini
[pytest]
addopts =
--benchmark-skip
EOF
オプションを何も付けずに実行すると、たしかにベンチマークテストが走らない。
$ pytest
=========================================================== test session starts ============================================================
platform darwin -- Python 3.7.3, pytest-4.4.1, py-1.8.0, pluggy-0.11.0
benchmark: 3.2.2 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /Users/amedama/Documents/temporary/pybench, inifile: pytest.ini
plugins: benchmark-3.2.2
collected 2 items
tests/test_example.py ss [100%]
======================================================== 2 skipped in 0.02 seconds =========================================================
なお、ベンチマークを実行したいときは --benchmark-only
オプションでオーバーライドできる。
$ pytest --benchmark-only
======================================================================== test session starts =========================================================================
platform darwin -- Python 3.7.3, pytest-4.4.1, py-1.8.0, pluggy-0.11.0
benchmark: 3.2.2 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /Users/amedama/Documents/temporary/pybench, inifile: pytest.ini
plugins: benchmark-3.2.2
collected 2 items
tests/test_example.py .. [100%]
--------------------------------------------------------------------------------------------- benchmark: 2 tests ---------------------------------------------------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_something_benchmark_quick 10.0553 (1.0) 12.7456 (1.0) 11.4637 (1.0) 1.0267 (1.37) 11.5810 (1.0) 2.2422 (2.07) 48;0 87.2316 (1.0) 84 1
test_something_benchmark_slow 1,003.0797 (99.76) 1,004.7923 (78.83) 1,003.6242 (87.55) 0.7500 (1.0) 1,003.1852 (86.62) 1.0816 (1.0) 1;0 0.9964 (0.01) 5 1
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Legend:
Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile.
OPS: Operations Per Second, computed as 1 / Mean
====================================================================== 2 passed in 9.06 seconds ======================================================================
表示する統計量を絞る
デフォルトでは結構色々な統計量が表示されるけど、正直そんなに細かくいらないという感じもある。
そういうときは --benchmark-column
オプションを使って必要なものだけに絞れる。
以下では試しに平均 (mean)、標準偏差 (stddev)、最小 (min)、最大 (max)だけ表示させてみた。
$ pytest --benchmark-only --benchmark-column=mean,stddev,min,max
======================================================================== test session starts =========================================================================
platform darwin -- Python 3.7.3, pytest-4.4.1, py-1.8.0, pluggy-0.11.0
benchmark: 3.2.2 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /Users/amedama/Documents/temporary/pybench, inifile: pytest.ini
plugins: benchmark-3.2.2
collected 2 items
tests/test_example.py .. [100%]
------------------------------------------------- benchmark: 2 tests ------------------------------------------------
Name (time in ms) Mean StdDev Min Max
---------------------------------------------------------------------------------------------------------------------
test_something_benchmark_quick 11.4288 (1.0) 1.0626 (1.0) 10.1003 (1.0) 12.7667 (1.0)
test_something_benchmark_slow 1,002.7103 (87.74) 1.9938 (1.88) 1,000.2403 (99.03) 1,005.2477 (78.74)
---------------------------------------------------------------------------------------------------------------------
Legend:
Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile.
OPS: Operations Per Second, computed as 1 / Mean
====================================================================== 2 passed in 9.04 seconds ======================================================================
表示される順番を変更する
pytest-benchmark では、デフォルトでテストの項目が平均実行時間 (mean) にもとづいて昇順ソートされる。
大抵の場合はデフォルトのままで問題ないはず。
とはいえ、念のため変更する方法についても確認しておく。
以下はテストごとに実行にかかる時間の分散を変更している。
テストの実行時間は対数正規分布にもとづいたランダムな時間になる。
ただし test_something_benchmark_high_stddev()
は test_something_benchmark_low_stddev()
よりもかかる時間の分散が大きくなるように設定している。
import time
import random
from functools import partial
import pytest
def something(duration_func):
time.sleep(duration_func())
return True
def test_something_benchmark_high_stddev(benchmark):
f = partial(random.lognormvariate, 0.01, 0.1)
ret = benchmark(something, duration_func=f)
assert ret
def test_something_benchmark_low_stddev(benchmark):
f = partial(random.lognormvariate, 0.1, 0.01)
ret = benchmark(something, duration_func=f)
assert ret
if __name__ == '__main__':
pytest.main(['-v', __file__])
上記で、試しに実行時間の標準偏差 (stddev) にもとづいたソートにしてみよう。
ソートの順番を変更するには --benchmark-sort
オプションでソートに使いたいカラムを指定する。
$ pytest --benchmark-only --benchmark-column=mean,stddev,min,max --benchmark-sort=stddev
======================================================================== test session starts =========================================================================
platform darwin -- Python 3.7.3, pytest-4.4.1, py-1.8.0, pluggy-0.11.0
benchmark: 3.2.2 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /Users/amedama/Documents/temporary/pybench, inifile: pytest.ini
plugins: benchmark-3.2.2
collected 2 items
tests/test_example.py .. [100%]
---------------------------------------------------- benchmark: 2 tests ----------------------------------------------------
Name (time in ms) Mean StdDev Min Max
----------------------------------------------------------------------------------------------------------------------------
test_something_benchmark_low_stddev 1,118.5442 (1.12) 11.9663 (1.0) 1,101.5850 (1.22) 1,132.8983 (1.03)
test_something_benchmark_high_stddev 1,002.3322 (1.0) 75.4297 (6.30) 900.1284 (1.0) 1,099.5439 (1.0)
----------------------------------------------------------------------------------------------------------------------------
Legend:
Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile.
OPS: Operations Per Second, computed as 1 / Mean
===================================================================== 2 passed in 15.86 seconds ======================================================================
上記を見ると、たしかに実行時間の標準偏差にもとづいて昇順ソートされている。
ある時点に比べてテストのパフォーマンスが低下していないか確認する
よくあるニーズとして、ある時点に比べてパフォーマンスが低下していないか確認したいというものがある。
pytest-benchmark では、もちろんこれも確認できる。
まずはシンプルなテストを用意する。
import time
import pytest
def something():
time.sleep(0.1)
return True
def test_something_benchmark(benchmark):
ret = benchmark(something)
assert ret
if __name__ == '__main__':
pytest.main(['-v', __file__])
テストを実行するときに --benchmark-autosave
オプションをつけると結果が保存される。
$ pytest --benchmark-only --benchmark-autosave
...(snip)...
=========================== 1 passed in 3.56 seconds ===========================
結果は .benchmarks
というディレクトリに JSON で保存される。
$ find .benchmarks
.benchmarks
.benchmarks/Darwin-CPython-3.7-64bit
.benchmarks/Darwin-CPython-3.7-64bit/0001_unversioned_20190520_123557.json
なお、複数回実行すると、その都度結果が記録されていく。
$ pytest --benchmark-only --benchmark-autosave
...(snip)...
=========================== 1 passed in 3.56 seconds ===========================
$ find .benchmarks
.benchmarks
.benchmarks/Darwin-CPython-3.7-64bit
.benchmarks/Darwin-CPython-3.7-64bit/0001_unversioned_20190520_123557.json
.benchmarks/Darwin-CPython-3.7-64bit/0002_unversioned_20190520_123739.json
ここで例えば、テストにかかる時間が 2 倍になるような変更をしてみよう。
import time
import pytest
def something():
time.sleep(0.2)
return True
def test_something_benchmark(benchmark):
ret = benchmark(something)
assert ret
if __name__ == '__main__':
pytest.main(['-v', __file__])
この状況で、過去のベンチマークとパフォーマンスを比較してみる。
次のように --benchmark-compare
オプションを使うと比較対象とするベンチマークを選べる。
また、--benchmark-compare-fail
オプションを併用することで、パフォーマンスが低下したときに結果をエラーにできる。
ここでは mean:5%
としているので、平均実行時間が 5% 悪化するとエラーになる。
$ pytest --benchmark-only --benchmark-compare=0002 --benchmark-compare-fail=mean:5%
Comparing against benchmarks from: Darwin-CPython-3.7-64bit/0002_unversioned_20190520_123739.json
======================================================================== test session starts =========================================================================
platform darwin -- Python 3.7.3, pytest-4.4.1, py-1.8.0, pluggy-0.11.0
benchmark: 3.2.2 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /Users/amedama/Documents/temporary/pybench, inifile: pytest.ini
plugins: benchmark-3.2.2
collected 1 item
tests/test_example.py . [100%]
--------------------------------------------------------------------------------------------- benchmark: 2 tests ---------------------------------------------------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_something_benchmark (0002_unversi) 100.1851 (1.0) 105.1182 (1.0) 102.8839 (1.0) 2.0469 (1.0) 103.4094 (1.0) 3.9875 (1.0) 5;0 9.7197 (1.0) 10 1
test_something_benchmark (NOW) 200.9856 (2.01) 205.1931 (1.95) 202.8940 (1.97) 2.1267 (1.04) 201.9794 (1.95) 4.0872 (1.02) 2;0 4.9287 (0.51) 5 1
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Legend:
Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile.
OPS: Operations Per Second, computed as 1 / Mean
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
Performance has regressed:
test_something_benchmark (0002_unversi) - Field 'mean' has failed PercentageRegressionCheck: 97.206794028 > 5.000000000
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
ERROR: Performance has regressed.
実行時間が 2 倍になっていることを考えれば当たり前だけどエラーになる。
いじょう。