Pythonのwith文で実行時間を測るクラスを書いた

Pythonwithブロックの実行時間を測るユーティリティクラスStopwatchを書いた。

複数のパラメータ・方式での実行速度を比較したい場合、計測結果をプログラム的にシームレスに取得してグラフ描画処理へと続けていきたくなる。Python でコード片の実行速度を測るなら、timeit を使うのが一般的だろう。しかし、どうにも timeit で計測結果をプログラム的に取得する方法が分からなかった。なので車輪の再発明をしてみた次第。

モノとしては単純で、Stopwatchオブジェクトをwith 文にて使用すると with ブロックの開始と終了の時間を測って内部的に記録する。実行時間は何度も計測することができ、mean()でそれらの平均、stdev()標準偏差を計算する。またstr()で文字列にするとtimeitっぽい形式で実行時間を表示するので、たとえば print() に渡せば結果を表示できる。実行例をいくつか:

>>> sw = Stopwatch()
>>> for _ in range(2):
...     with sw:
...         sum(n for n in range(1_000_000))
>>> print(sw)
64.4 ms ± 5.05 ms per laps (mean ± std. dev. of 2 laps)
>>> sw.mean('ms'), sw.stdev('ms')
(64.3803169889452, 5.054087780470232)

また、Stopwatch オブジェクトの生成時に print 関数や logging.debug 関数を渡してやると、with ブロックを抜けるたびにその関数で実行時間を表示する:

>>> sw = Stopwatch(print)
>>> for _ in range(2):
...     with sw:
...         sum(n for n in range(1_000_000))
73.8 ms ± nan ms per laps (mean ± std. dev. of 1 laps)
67.4 ms ± 8.97 ms per laps (mean ± std. dev. of 2 laps)

実装コードは Gist として、GitHub で公開中。

gist.github.com