パターンマッチングを行うクラスを実験してきました。私のクラスは次のようになります。
class Matcher(object):
def __init__(self, pattern):
self._re = re.compile(pattern)
def match(self, value):
return self._re.match(value)
全体として、私のスクリプトの実行には約 45 秒かかります。実験として、コードを次のように変更しました。
class Matcher(object):
def __init__(self, pattern):
self._re = re.compile(pattern)
self.match = self._re.match
このスクリプトの実行には 37 秒かかりました。このプロセスを何度繰り返しても、同じようにパフォーマンスが大幅に向上します。cProfile を介して実行すると、次のように表示されます。
ncalls tottime percall cumtime percall filename:lineno(function)
46100979 14.356 0.000 14.356 0.000 {method 'match' of '_sre.SRE_Pattern' objects}
44839409 9.287 0.000 20.031 0.000 matcher.py:266(match)
なぜマッチメソッドは実行時間に 9.2 秒を追加するのでしょうか? 最も苛立たしいのは、単純なケースを再現しようとして、再現できなかったことです。ここで何が欠けていますか?私の簡単なテスト ケースにバグがありました。今、私が見ている動作を模倣しています:
import re
import sys
import time
class X(object):
def __init__(self):
self._re = re.compile('.*a')
def match(self, value):
return self._re.match(value)
class Y(object):
def __init__(self):
self._re = re.compile('ba')
self.match = self._re.match
inp = 'ba'
x = X()
y = Y()
sys.stdout.write("Testing with a method...")
sys.stdout.flush()
start = time.time()
for i in range(100000000):
m = x.match(inp)
end = time.time()
sys.stdout.write("Done: "+str(end-start)+"\n")
sys.stdout.write("Testing with an attribute...")
sys.stdout.flush()
start = time.time()
for i in range(100000000):
m = y.match(inp)
end = time.time()
sys.stdout.write("Done: "+str(end-start)+"\n")
出力:
$ python speedtest.py
Testing with a method...Done: 50.6646981239
Testing with an attribute...Done: 35.5526258945
参考までに、どちらもpyp を使用するとはるかに高速ですが、メソッドの代わりに属性を使用して実行すると、大幅な改善が見られます。
$ pypy speedtest.py
Testing with a method...Done: 6.15996003151
Testing with an attribute...Done: 3.57215714455