私はPython 3.3でこのスクリプトを実行しようとしました。 残念ながら、それはPython 2.7より約2倍遅いです。ここでなぜPython 3.3で印刷が遅くなり、どうすれば修正できますか?
#!/usr/bin/env python
from sys import stdin
def main():
for line in stdin:
try:
fields = line.split('"', 6)
print(fields[5])
except:
pass
if __name__ == '__main__':
main()
結果は以下のとおりです。
$ time zcat access.log.gz | python3 -m cProfile ./ua.py > /dev/null
real 0m13.276s
user 0m18.977s
sys 0m0.484s
$ time zcat access.log.gz | python2 -m cProfile ./ua.py > /dev/null
real 0m6.139s
user 0m11.693s
sys 0m0.408s
プロファイリングは、追加の時間が印刷に費やすであることを示しています
$ zcat access.log.gz | python3 -m cProfile ./ua.py | tail -15
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.000 0.000 <frozen importlib._bootstrap>:1594(_handle_fromlist)
196806 0.234 0.000 0.545 0.000 codecs.py:298(decode)
1 0.000 0.000 13.598 13.598 ua.py:3(<module>)
1 4.838 4.838 13.598 13.598 ua.py:6(main)
1 0.000 0.000 13.598 13.598 {built-in method exec}
1 0.000 0.000 0.000 0.000 {built-in method hasattr}
4300456 4.726 0.000 4.726 0.000 {built-in method print}
196806 0.312 0.000 0.312 0.000 {built-in method utf_8_decode}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
4300456 3.489 0.000 3.489 0.000 {method 'split' of 'str' objects}
$ zcat access.log.gz | python2 -m cProfile ./ua.py | tail -10
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 6.573 6.573 ua.py:3(<module>)
1 3.894 3.894 6.573 6.573 ua.py:6(main)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
4300456 2.680 0.000 2.680 0.000 {method 'split' of 'str' objects}
どのように私は、このオーバーヘッドを回避することができますか?それはUTF-8と関係がありますか?
さて、 'print'はpython3ではもう文ではありませんので、いくらかのオーバーヘッドが予想されます。これはおそらく 'sys.stdout.write'を使うか、あるいはメモリの問題ではないことを前提として、文字列のリストを作成してから' sys.stdout.writelines'を使うことで、もっと少なくなります。どちらの場合でも、 'print'で作成した改行を自分で追加する必要があります。 – l4mpi