Pythonのtimeitモジュールは、小さなコードブロックの実行時間を素早く計測するためのシンプルなインターフェイスです。
アプリケーションを作成するとき、このコードのブロックはどのように動作するのだろうかと疑問に思い、異なるシナリオの下でテストしたいと思うかもしれません。
この問題に対して、 timeit モジュールは非常にシンプルな解決策を提供します。
それでは、このモジュールを使ってコードスニペットの時間を計る方法を見てみましょう。
ここでは、コマンドラインインターフェイスと呼び出し可能なインターフェイスの両方について見ていきます。
Python timeit – コマンドラインインターフェース
コマンドラインインターフェースは、Pythonのプログラムを実行する場合と非常によく似ています。
m オプションを使って外部モジュール timeit をインポートし、あなたのコードに適用する必要があります。
python -m timeit 'print("Hello from Python")'
|
これは、文字列として渡されたスニペットを timeit を使って実行します。
デフォルトでは、Linuxで100万回、Windowsで2000万回実行され、その中から最適な時間を計測します。
以下の出力は、私のLinuxシステムでのものです。
import timeit
|
もし、あなたのスニペットの中にすでにforループがある場合、このモジュールは反復処理の合計が100万回に近いことを確認し、あなたのループ全体が100万回実行されないことに注意してください!
execution_time = timeit.timeit(code, number)
|
Python timeit – Python インターフェース
Python インタープリタ経由で timeit を使用することも可能で、その場合は次のようにインポートします。
>>> import timeit
>>> timeit.timeit('"-".join(str(n) for n in range(100))', number=10000)
0.19053685299877543>>> timeit.timeit('"-".join([str(n) for n in range(100)])', number=10000)
0.172546762998536>>> timeit.timeit('"-".join(map(str, range(100)))', number=10000)
0.13625987299747067>>> |
実行時間を知るには、コードを文字列として timeit.timeit() に渡します。
setup_code = "import math"
|
パラメータ number を使って、反復処理の回数を制御することができる。
execution_time = timeit.timeit(setup = setup_code, stmt = main_block, number = 100)
|
timeit モジュールの使用
それでは、プログラムの中でスニペットの時間を計るために timeit をどのように使うか見てみましょう。
しかしその前に、あなたはあることに疑問を持つかもしれません。
この問題の解決策は、必要なモジュールと変数のセットアップを行うセットアップコードブロックを使用することです。
import timeit
# Setup is run only oncesetup_code = '''
import numpy as npa = np.arange(0, 1000)print(a.shape)def print_subarrays(a): op = []
for i in range(a.shape[0]):
op.append(a[:i])
'''main_block = '''
print_subarrays(a)'''# Main Block is run 1000 timesprint('Best execution Time among 1000 iterations:', timeit.timeit(setup=setup_code, stmt=main_block, number=1000))
|
セットアップブロックの書き方はとても簡単です。
必要なコードを書き、それを文字列として変数に渡すだけです。
この後、メインのコードブロックを書いて、 setup と stmt パラメータを使って timeit.timeit() に渡します。
(1000,)
Best execution Time among 1000 iterations: 0.3830194959991786
|
timeit` は、メインループが計測される前にセットアップを行うので、一度だけ実行されます。
では、早速例を見てみましょう。
このコードは、numpyの配列の開始要素からすべての部分配列を取得しようとするものです。
セットアップブロックが一度だけ実行されることに注意してください。
import timeit
start_time = timeit.default_timer()
function_1()time_1 = timeit.default_timer() - start_time
start_time = timeit.default_timer()
function_2()time_2 = timeit.default_timer() - start_time
print('Function 1 took', time_1)
print('Function 2 took', time_2)
|
結果は以下の通りです。
import timeit
import numpy as np
def time_range(size):
for i in range(size):
pass
def time_arange(size):
np.arange(size)
if __name__ == '__main__':
# For smaller arrays
print('Array size: 1000')
start_time = timeit.default_timer();
time_range(1000)
range_time_1 = timeit.default_timer() - start_time
start_time = timeit.default_timer();
time_arange(1000)
arange_time_1 = timeit.default_timer() - start_time
# For large arrays
print('Array size: 1000000')
start_time = timeit.default_timer();
time_range(1000000)
range_time_2 = timeit.default_timer() - start_time
start_time = timeit.default_timer();
time_arange(1000000)
arange_time_2 = timeit.default_timer() - start_time
print(f'size 1000: range() took {range_time_1}')
print(f'size 1000: arange() took {arange_time_1}')
print(f'size 1000000: range() took {range_time_2}')
print(f'size 1000000: arange() took {arange_time_2}')
|
コードブロックの性能を比較する
複数のコードブロックのパフォーマンスを timeit を使って簡単に比較することができます。
ここでは、timeit.default_timer()を使用して、タイマーを使用します。
コードブロックにかかった時間は、現在時刻から参照として取得した初期時刻を引いたものとなり、変数で渡すことができます。
Array size: 1000
Array size: 1000000
size 1000: range() took 2.2970001737121493e-05
size 1000: arange() took 8.393999451072887e-06
size 1000000: range() took 0.02567379199899733
size 1000000: arange() took 0.0031752489994687494
|
numpyの配列に対する2つの関数 range() と np.arange() をテストして、両者を比較してみましょう。
python -m timeit -s 'import numpy_compare' 'numpy_compare.time_range(1000)'
|
結果は以下の通りです。

このように、timeit を使って簡単に異なる関数のパフォーマンスを比較することができます。
この記事もチェック:Pythonでdatatimeモジュールを使って現在の日付と時刻を取得する方法
Time a Particular Function
他のコードブロックを実行せずに、スクリプト内の特定の関数のパフォーマンスのみを計測することもできます。
先ほどのファイルがnumpy_compare.pyであったとすると、以下のように実行時間を求めることができます。

結果は以下の通りです。

まとめ
このモジュールの基本的な使い方はご理解いただけたと思いますので、さっそく使って生産性を高めていきましょう!