Pythonで実行時間を計測する方法 その1
IPythonで実行時間を計測するには、%timeitなどのマジックコマンドを用いればいいのですが、IPythonが入っていない環境で実行時間を計測したくなった場合は以下のようにデコレータを用いる方法があります。
timeデコレータの定義
高階関数を定義するのに便利なfunctoolsを使って、デコレータを定義します。
functoolsをデコレータで用いる意味については、この記事の末尾の参照の記事を見てください。
def time(func):
import functools
import datetime
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = datetime.datetime.today()
result = func(*args, **kwargs)
end = datetime.datetime.today()
return end - start
return wrapper
timeデコレータで関数をデコレート
Pythonのリスト内包表記で使った関数に対してデコレータを試します。
上で定義したtimeデコレータを使うには、関数定義が始まる前の行に@timeを付けます。
もともとの関数の中身は何も変えていないことに注目して頂きたいと思います。
# 1. testfunc1: 空リストを用意してappend
@time
def testfunc1(rangelist):
templist = []
for temp in rangelist:
templist.append(temp)
# 2. testfunc2: 1+appendをオブジェクト化
@time
def testfunc2(rangelist):
templist = []
append = templist.append
for temp in rangelist:
append(temp)
# 3. testfunc3: リスト内包表記
@time
def testfunc3(rangelist):
templist = [temp for temp in rangelist]
デコレータ付き関数の実行
デコレータを付けた関数を呼び出してみました。
>>> rangelist = range(1,10000000)
>>> testfunc1(rangelist)
datetime.timedelta(0, 0, 303000)
>>> testfunc2(rangelist)
datetime.timedelta(0, 0, 267000)
>>> testfunc3(rangelist)
datetime.timedelta(0, 0, 70000)
10回実行して平均をとる
10回実行して、平均をとるには以下のようにします。
本当は、一回目の結果を捨てたり、いろいろしないといけない気がしますが、気にしないことにします。
>>> print reduce(lambda x, y: x + y, [testfunc1(rangelist) for temp in range(10)])/10
0:00:00.266600
>>> print reduce(lambda x, y: x + y, [testfunc2(rangelist) for temp in range(10)])/10
0:00:00.246300
>>> print reduce(lambda x, y: x + y, [testfunc3(rangelist) for temp in range(10)])/10
0:00:00.056100
sumを使ったらうまくいかなかったので、reduceにしました。
参考
functoolについては、以下のサイトを参考にしました。