2012-05-11 4 views
3

にそのバイト文字表現に整数に変換するとき、Pythonの2.xでPythonの3.xの性能iは整数に変換する必要がある。具体的にはPython

までのpython 2.6のバイトに9999b'9999'を言いますpython 2.6

でのpython 3.xでは

('%s'%n).encode() 

パフォーマンスながら、私は

b'%s'%n 

を行います私のベンチマークが正しく設定されていると仮定すると、Pythonで10

>>> from timeit import Timer 
>>> Timer('b"%s"%n','n=9999').timeit() 
0.24728001750963813 

パフォーマンス3.2

>>> from timeit import Timer 
>>> Timer('("%s"%n).encode()','n=9999').timeit() 
0.534475012767416 

は、それはPythonの3.xで多額の違約金あり

2.6/2.7でギャップを閉じるためにパフォーマンスを改善する方法はありますか?

多分cython経由でですか?

これは私が最適化しようとしているジェネレータ関数です。それはargsは、文字列のリストであることを何度も呼ばれ、バイトまたは番号:

def pack_gen(self, args, encoding='utf-8'): 
    crlf = b'\r\n' 
    yield ('*%s\r\n'%len(args)).encode(encoding) 
    for value in args: 
     if not isinstance(value, bytes): 
      value = ('%s'%value).encode(encoding) 
     yield ('$%s\r\n'%len(value)).encode(encoding) 
     yield value 
     yield crlf 

機能が、私はのreprを使用して少しでも良い結果を持っている

b''.join(pack_gen(args)) 
+1

なぜバイトである必要がありますか? –

+2

最初に文字列に変換してからバイトに変換する必要があるので、大きなペナルティです。私はその周りに道を見ない。問題はそれが本当に関連しているかどうかです。これは実際にアプリケーションで大きなパフォーマンス上のペナルティですか? –

+0

はい、そうです。常に呼び出される関数の長いループの内部にあります。 –

答えて

0

このように呼ばれています()はPython 3.2で:

>>> Timer('repr(n).encode()','n=9999').timeit() 
0.32432007789611816 
>>> Timer('("%s" % n).encode()','n=9999').timeit() 
0.44790005683898926 

しかし、もちろん、それは"%s" % nほど柔軟ではありません。

私もPEP393変換少し意外にも、私は3.2よりも悪い結果を持っているをスピードアップすることを期待して、Pythonの3.3.0a3をチェックしました:

>>> Timer('repr(n).encode()','n=9999').timeit() 
0.35951611599921307 
>>> Timer('("%s"%n).encode()','n=9999').timeit() 
0.4658188759985933 
最後に

、以下:

>>> Timer('str(n).encode()','n=9999').timeit() 
0.49958825100111426 

は、ほとんどのコストが関数呼び出しのオーバーヘッドから来ていることを示しています(上記の結果から、整数型のPython実装str()が内部でrepr()を呼び出すと仮定しています)。したがって、このレベルで最適化する必要がある場合は、提案したように、cythonを使用してコードブロック全体を置き換えることができます。あるいは、最適化しようとしているループを見せてください。スピードを上げるための他の多くの方法があるかもしれません。

+0

質問本体にユースケースを追加しました。 –

関連する問題