Pythonで特定の処理群を実行するのにかかる時間を計測するにはtimeit
というモジュールを用いる。
まず準備としてtimeit
モジュールをインポートして使用可能にしておく。
import timeit
timeit.time()
の最初の引数1にPythonのコードの文字列(クォートされた文字列か、文字列の入った変数)を渡すsetup
に同様の形で渡した文字列は、実行時間計測の前に変数などの準備を行うPythonコードを渡すのに使える
number
でそのコードの実行を何回繰り返すかを指定
この関数の戻り値として処理時間が得られる。
他の言語の処理時間計測用の関数やオブジェクトでは計測開始や計測停止のタイミングで関数を呼び出すが、この方法はそれとは大きく使い方が異なる。
リスト型とcollections.deque
型のそれぞれに連番を入れておき、最初の値を取り出して除くのを全要素に行うのにかかる時間を比べてみる。
(リスト型)
>>> timeit.timeit("while len(lst) > 0: lst.pop(0)", setup="lst = []\nfor i in range(114514): lst.append(i)")
3.4290177009997933
(collections.deque型)
>>> timeit.timeit("while len(que) > 0: que.popleft()", setup="from collections import deque\nque = deque([])\nfor i in range(114514): que.append(i)")
0.12383000899990293
リストをキューとして使う(=最初に入れたデータを最初に取り出す)よりはcollections.deque
型を使用したほうが圧倒的に速い2ということが分かる。
なお、変数の準備の記述が後ろに来ると全体の流れが見づらい場合にはキーワード引数stmt
を後ろに持ってくると見やすくなる場合がある。
(stmtを後ろに配置した例)
>>> timeit.timeit(setup="lst = []\nfor i in range(114514): lst.append(i)", stmt="while len(lst) > 0: lst.pop(0)")
>>> timeit.timeit(setup="from collections import deque\nque = deque([])\nfor i in range(114514): que.append(i)", stmt="while len(que) > 0: que.popleft()")
クラスを用いる方法は処理時間計測の部分を何回も繰り返す場合などに便利。
timeit.Timer()
クラスのオブジェクトを作成
stmt
やsetup
といった引数は作成時の引数として渡すtimeit()
を呼び出すたびに処理時間の結果が得られる
number
引数を指定する場合はここで指定する(オブジェクト作成)
>>> t = timeit.Timer(setup="from collections import deque\nlst = deque([])\nfor i in range(114514): lst.append(i)", stmt="while len(lst) > 0: lst.popleft()")
(処理時間計測)
>>> t.timeit(number=10000000)
0.9805724760008161
(更に繰り返し実行してみる)
>>> t.timeit(number=10000000)
0.9808024780013511
>>> t.timeit(number=10000000)
0.9857495670003118
スクリプトの中で処理時間を計測したい部分を関数にしておいて、timeit.timeit()
でその関数の呼び出し処理をstmt
引数に記述しておくと便利なことがある。
その際、関数の名前が実行時に未定義となってエラーにならないようにglobals=globals()
指定を追加するとよい。
#! /usr/bin/python3
import timeit
from collections import deque
def prep_list(length):
lst = []
for i in range(length):
lst.append(i)
return lst
def prep_deque(length):
que = deque([])
for i in range(length):
que.append(i)
return que
def do_task_list(lst):
while len(lst) > 0:
lst.pop(0)
def do_task_deque(que):
while len(que) > 0:
que.popleft()
if __name__ == "__main__":
data_len = 114514
print(
"list -> {}".format(
timeit.timeit(
setup="q = prep_list({})".format(data_len),
stmt="do_task_list(q)",
globals=globals())))
print(
"deque -> {}".format(
timeit.timeit(
setup="q = prep_deque({})".format(data_len),
stmt="do_task_deque(q)",
globals=globals())))
出力例:
list -> 3.4471844719992077
deque -> 0.23104157700072392