リストに要素を追加する処理速度の比較
前提
処理速度の比較として、Pythonの公式実装であるCPythonと、PythonのPythonによるJITコンパイラ実装であるPyPyの実行時間について比較しました。
Pythonのリスト内包表記で使った以下の3つの関数に対して、Pythonで実行時間を計測する方法 その1で定義したデコレータを用いました。
評価対象の関数
# 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]
時間計測用デコレータ
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
CPythonとPyPyのバージョンは以下の通りです。
CPython
Python 2.7.4 (default, Apr 6 2013, 19:54:46) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
PyPy
Python 2.7.3 (87aa9de10f9c, Nov 24 2013, 17:46:53)
[PyPy 2.2.1 with MSC :.1500 32 bit] on win32
Type "help", "copyright", "credits" or "license" for more information
And now for something completely different: ``PyPy 1.3 released''
結果
それぞれの関数に対し、10,000,000個の要素をリストに追加する処理を10回行い、その平均実行時間を取得しました。
CPython
>>> rangelist = range(1,10000000)
>>> print reduce(lambda x, y: x + y, [testfunc1(rangelist) for temp in range(0,10)])/10
0:00:00.998600
>>> print reduce(lambda x, y: x + y, [testfunc2(rangelist) for temp in range(0,10)])/10
0:00:00.723500
>>> print reduce(lambda x, y: x + y, [testfunc3(rangelist) for temp in range(0,10)])/10
0:00:00.399900
PyPy
>>> rangelist = range(1,10000000)
>>> print reduce(lambda x, y: x + y, [testfunc1(rangelist) for temp in range(0,10)])/10
0:00:00.290300
>>> print reduce(lambda x, y: x + y, [testfunc2(rangelist) for temp in range(0,10)])/10
0:00:00.275500
>>> print reduce(lambda x, y: x + y, [testfunc3(rangelist) for temp in range(0,10)])/10
0:00:00.046300
厳密に比較するには、最初の一回を抜いたりいろいろ必要ですが、ここでは何もしていません。
結論
それぞれの倍率(CPythonの実行時間÷PyPyの実行時間)は以下の通りです。数値が大きいほどPyPyが高速であることを意味します。
- testfunc1: 3.43
- testfunc2: 2.62
- testfunc3: 8.63
PyPyでは、testfunc3、つまりリスト内包表記版が特に高速化しています。
JITコンパイラ関連でLuaを勉強しようかなと思っていましたが、これならPyPyを勉強するべきだと思いました。