コードをプロファイリングして、ボトルネックの場所を把握できます。以下は、プロファイリング情報を含む「cart_stats.txt」というファイルを作成します。自分で実行すると、ほとんどの時間が呼び出しに費やされていることがわかりfile.write()
ます。
from cProfile import Profile
from pstats import Stats
prof = Profile()
prof.disable()
file = open('cart_output.txt', 'wt')
def cart(n, seq):
import itertools
b = 8
while b < n:
n = n - 1
for p in itertools.product(seq, repeat=n):
file.write(''.join(p))
file.write('\n')
prof.enable()
cart(10, 'abc')
prof.disable()
prof.dump_stats('cart.stats')
with open('cart_stats.txt', 'wt') as output:
stats = Stats('cart.stats', stream=output)
stats.sort_stats('cumulative', 'time')
stats.print_stats()
file.close()
print 'done'
FWIW、巨大なバッファで出力ストリームを出力したり、インスタンスにしたりしても、遅さはfile.write()
それ自体への呼び出しが圧倒的に原因であるようです。以下に示すように、呼び出しを最適化および最小化することで、それを大幅に削減できました。open()
StringIO
def cart(n, seq):
import itertools
b = 8
write = file.write # speed up lookup of method
while b < n:
n = n - 1
for p in itertools.product(seq, repeat=n):
write(''.join(p)+'\n') # only call it once in loop
これは、プロファイラーを配置することが、どこに時間を費やして最大の利益を得るかを知るための最良の方法であることを証明しています.
アップデート:
単一のfile.write()
呼び出しを行う前に、生成されたすべての出力をメモリに保存するバージョンを次に示します。一般的ではないため、using よりも大幅に高速ですが、インスタンスStringIO.StringIO
を使用するほど高速ではありません。cStringIO.StringIO
file = open('cart_output.txt', 'wt')
def cart(n, seq):
from itertools import product
buflist = []
append = buflist.append
b = 8
while b < n:
n = n - 1
for p in product(seq, repeat=n):
append(''.join(p))
file.write('\n'.join(buflist)+'\n')
file.close()