はじめに
- 今回はPython標準ライブラリのtimeitモジュールを使って、プログラムの処理時間を計測してみたいと思います。
- 動作環境
- Python 3.11.0
- macOS Ventura
timeitとは
timeitはPython標準ライブラリのモジュールで、小さなコードの計測に便利です。
timeitモジュールは、コードの一部を指定した回数だけ実行することで、その処理速度を計測して、平均処理時間を計測できます。また、デフォルトでは計測中、一時的にガベージコレクションを無効にすることで、個々の計測結果がより比較しやすくなります。
timeitを使って以下の3つのやり方で処理時間を計測してみます。
- pyファイル内で計測
- コマンドラインで計測
- 対話モードで計測
※処理時間は実行するマシンの性能によって異なる場合があります。
pyファイル内で計測
timeit.timeit()
import timeit
timeit.timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000, globals=None)
timeit.timeit()は測定対象となるコード、setupコードおよび timer関数でTimerインスタンスを作成し、そのtimeit()メソッドをnumber回
実行します。(デフォルトは100万回)
複数行を計測したい場合は、複数行のコード文字列を渡すか、セミコロンで区切ります。
例えば、2つの変数の値の入れ替え時に、一般的な方法として、一時変数を使う方法と、アンパックを使う方法がありますが、どちらの方が速いか知りたい場合は、以下のように測定できます。
import timeit
# 一時変数を使った変数の値の入れ替え
print(timeit.timeit("a, b = 1, 2; temp = a; a = b; b = temp"))
# アンパックを使った変数の値の入れ替え
print(timeit.timeit("a, b = 1, 2; a, b = b, a"))
それぞれの(100万回実行した)処理時間が以下のように秒単位
で出力されます。(アンパックの方が速いですね)
0.022119374996691477
0.01498649999848567
また、以下のように合計処理時間を実行回数で割ることで平均処理時間
を計測できます。
import timeit
# 2の100000乗を10万回計算し、その平均処理時間を計測
print(timeit.timeit("2 ** 100000", number=100000) / 100000)
0.0002520138779199624
実行回数で割らないと1回あたりの処理時間ではなく、合計処理時間になるのでご注意ください。また、重い処理の場合は終了まで時間がかかるのでnumberを減らしたほうがいいでしょう。
setup引数には測定前に実行する処理
を記述できます。
import timeit
# 1から100までの乱数を1000万回生成し、その合計処理時間を計測
# 測定前に乱数生成のためのrandomをimport
print(timeit.timeit("random.randint(1, 100)", setup="import random", number=10000000))
2.021007332994486
globals引数にはコードを実行する名前空間
を指定します。デフォルトではtimeit.timeit()に渡す測定対象となるコードは、プログラムにある他の変数や関数にアクセスできません。globals()を指定することでグローバルな名前空間
でコードを実行できます。
import timeit
# sという変数を設定
s = "hello"
# sを1回出力する時間を測定
print(timeit.timeit("print(s)", number=1, globals=globals()))
hello
1.9999999494757503e-05
timeit.repeat()
import timeit
timeit.repeat(stmt='pass', setup='pass', timer=<default timer>, repeat=5, number=1000000, globals=None)
timeit.repeat()はtimeit()をrepeat回
実行できます。(デフォルトは5回)
結果はリスト
で返ってきます。setupやglobalsなどの引数の使い方はtimeit.timeit()と同じです。
import timeit
# 1から100までの乱数を1000万回生成する処理を3回実行し、それぞれの処理時間を計測
print(timeit.repeat("random.randint(1, 100)",
setup="import random", repeat=3, number=10000000))
[2.0110499169968534, 1.9915823749979609, 1.9966460420037038]
コマンドラインで計測
コマンドラインからプログラムとして呼び出す場合は、以下のコマンドを使います。(オプションの説明はhelpオプションか公式ドキュメントをご参照ください)
python3 -m timeit [-n N] [-r N] [-u U] [-s S] [-h] [statement ...]
1から100までの乱数を1000万回生成する処理を3回実行するコマンドを実行してみます。
python3 -m timeit -n 10000000 -r 3 -s "import random" "random.randint(1, 100)"
3回実行した中で最も速かった平均値
(1から100までの乱数を生成する処理の1回あたりの処理時間)が出力されます。(200ナノ秒)
10000000 loops, best of 3: 200 nsec per loop
対話モードで計測
pyファイル内で計測するのとほぼ同じやり方です。スクリプトを書くまでもないちょっとした動作確認の際に使うといいでしょう。
ターミナルで対話モード(インタラクティブモード)でpythonを起動して、timeit.timeit()を使って、1から100までの乱数を1000万回生成し、その処理時間を計測してみます。
>>> import timeit
>>> timeit.timeit("random.randint(1, 100)", setup="import random", number=10000000)
2.044745207997039
>>>