pyre2
( https://github.com/axiak/pyre2 )を使用すると、パフォーマンスの問題 (マッチング時間) が発生しました。
私は3つのプログラムを持っています:
組み込みの re モジュールを使用した純粋な Python: https://gist.github.com/1873402
Pyre2 を使用した Python: https://gist.github.com/1873402。(コードの大部分は第 1 のプログラムと同じです。組み込みの re を使用する場合を除いて、utf-8 文字列を unicode にデコードします。これは pyre2 を使用する場合には必要ありません)
re2 を使用した C/C++: https://gist.github.com/1873417
正規表現のプリコンパイル時間とマッチング時間の 2 つの時間を測定しました。
No.1 プログラム: 1.65 秒 1.25 秒
第2プログラム: 0.04s 1.8s
第3プログラム: 0.02s 0.8s
それらはすべて同じ正規表現と入力によって供給されます。(すべての正規表現は でサポートされていre2
ます)
次に、Cython でのプロファイリングに関するドキュメントに従いました。次の結果が得られました。
ncalls tottime percall cumtime percall filename:lineno(関数) 652884 16.477 0.000 25.349 0.000 re2.pyx:394(_search) 9479 6.059 0.001 41.806 0.004 export_plain.py:60(一致) 652884 4.243 0.000 33.602 0.000 {「re2.Pattern」オブジェクトのメソッド「検索」} 652884 4.010 0.000 29.359 0.000 re2.pyx:442(検索) 652884 3.056 0.000 3.056 0.000 re2.pyx:114(__init__) 652953 2.145 0.000 2.145 0.000 {インスタンス} 652884 2.002 0.000 2.002 0.000 re2.pyx:123(__dealloc__) 652953 1.911 0.000 1.911 0.000 re2.pyx:75(unicode_to_bytestring) 652953 1.902 0.000 1.902 0.000 re2.pyx:86(pystring_to_bytestring) 1 0.330 0.330 42.492 42.492 export_plain.py:98(export_fname) 9479 0.173 0.000 0.173 0.000 {組み込みメソッド サブ} 10000 0.120 0.000 0.120 0.000 {「str」オブジェクトのメソッド「分割」} 8967 0.063 0.000 0.099 0.000 re2.pyx:801(取得) 10069 0.061 0.000 0.061 0.000 {「str」オブジェクトのメソッド「ストリップ」} 69 0.043 0.001 0.146 0.002 re2.pyx:806(prepare_pattern) 9036 0.038 0.000 0.038 0.000 re2.pyx:788(__next) 69 0.022 0.000 0.169 0.002 re2.pyx:905(_コンパイル) 1 0.005 0.005 0.177 0.177 export_plain.py:36(ロード) 69 0.002 0.000 0.003 0.000 re2.pyx:784(__init__) 69 0.001 0.000 0.170 0.002 re2.pyx:763(コンパイル) 38 0.001 0.000 0.001 0.000 {「ファイル」オブジェクトのメソッド「書き込み」} 69 0.001 0.000 0.171 0.002 {re2.compile} 1 0.001 0.001 42.669 42.669 export_plain.py:160(メイン) 3 0.000 0.000 0.000 0.000 {オープン} 69 0.000 0.000 0.000 0.000 {「リスト」オブジェクトのメソッド「追加」} 19 0.000 0.000 0.000 0.000 {「str」オブジェクトの「結合」メソッド} 1 0.000 0.000 0.000 0.000 ジェネリックパス.py:38(isdir) 1 0.000 0.000 42.669 42.669 export_plain.py:153(run_re2_test) 1 0.000 0.000 0.000 0.000 {posix.stat} 4 0.000 0.000 0.000 0.000 {時間.時間} 1 0.000 0.000 0.000 0.000 posixpath.py:59(結合) 1 0.000 0.000 42.670 42.670 :1() 1 0.000 0.000 0.000 0.000 {'unicode' オブジェクトの 'encode' メソッド} 3 0.000 0.000 0.000 0.000 {'str' オブジェクトのメソッド 'rfind'} 2 0.000 0.000 0.000 0.000 posixpath.py:109(ベース名) 1 0.000 0.000 0.000 0.000 posixpath.py:117(ディレクトリ名) 1 0.000 0.000 0.000 0.000 stat.py:40(S_ISDIR) 2 0.000 0.000 0.000 0.000 {レン} 1 0.000 0.000 0.000 0.000 {「リスト」オブジェクトの「拡張」メソッド} 1 0.000 0.000 0.000 0.000 {'str' オブジェクトの 'startswith' メソッド} 1 0.000 0.000 0.000 0.000 {'str' オブジェクトの 'endswith' メソッド} 1 0.000 0.000 0.000 0.000 stat.py:24(S_IFMT) 1 0.000 0.000 0.000 0.000 {「ファイル」オブジェクトのメソッド「__enter__」} 1 0.000 0.000 0.000 0.000 {「_lsprof.Profiler」オブジェクトのメソッド「無効」}
_search
関数 (re2.pyx:393) に時間がかかりすぎているようです。しかし、これと純粋なCバージョンとの間でどのように違いがあるのか わかりません。
PS: Pyre2 リビジョン: コミット543f228
re2 リビジョン: 変更セット:79:0c439a6bd795
実際のMatch
関数 (re2.pyx:424) は、この関数でほとんどの時間を費やしていると思います。
次に、 Match 関数を cdef 関数にリファクタリング_my_match
して、プロファイル結果で確認できるようにし、 cdef function へのStringPiece
割り当てもリファクタリングします_alloc_sp
。(変更の詳細: https://gist.github.com/1873993 ) 再プロファイリングしてから取得:
月 2 月 20 日 20:52:47 2012 Profile.prof 28.265 CPU 秒で 3975043 回の関数呼び出し 並べ替え: 内部時間 ncalls tottime percall cumtime percall filename:lineno(関数) 652884 10.060 0.000 20.230 0.000 re2.pyx:452(検索) 652884 4.131 0.000 28.201 0.000 {「re2.Pattern」オブジェクトの「検索」メソッド} 652884 3.647 0.000 3.647 0.000 re2.pyx:394(_my_match) 9479 3.037 0.000 31.238 0.003 export_plain.py:62(一致) 652884 2.901 0.000 2.901 0.000 re2.pyx:443(_alloc_sp) 652953 1.814 0.000 1.814 0.000 re2.pyx:86(pystring_to_bytestring) 652953 1.808 0.000 1.808 0.000 re2.pyx:75(unicode_to_bytestring) 1 0.332 0.332 31.926 31.926 export_plain.py:96(export_fname) 9479 0.169 0.000 0.169 0.000 {組み込みメソッド サブ} 10000 0.122 0.000 0.122 0.000 {「str」オブジェクトのメソッド「分割」} 8967 0.065 0.000 0.099 0.000 re2.pyx:849(取得) 10069 0.064 0.000 0.064 0.000 {「str」オブジェクトのメソッド「ストリップ」} 69 0.042 0.001 0.142 0.002 re2.pyx:854(prepare_pattern) 9036 0.035 0.000 0.035 0.000 re2.pyx:836(__next) 69 0.023 0.000 0.166 0.002 re2.pyx:953(_コンパイル) 1 0.003 0.003 32.103 32.103 export_plain.py:158(メイン) 1 0.003 0.003 0.174 0.174 export_plain.py:36(ロード) 69 0.002 0.000 0.168 0.002 re2.pyx:811(コンパイル) 38 0.001 0.000 0.001 0.000 {「ファイル」オブジェクトのメソッド「書き込み」} 69 0.001 0.000 0.169 0.002 {re2.compile} 69 0.001 0.000 0.001 0.000 re2.pyx:832(__init__) 1 0.001 0.001 32.104 32.104 export_plain.py:151(run_re2_test) 1 0.000 0.000 32.105 32.105 :1() 2 0.000 0.000 0.000 0.000 {レン} 3 0.000 0.000 0.000 0.000 {オープン} 1 0.000 0.000 0.000 0.000 {「リスト」オブジェクトの「拡張」メソッド} 69 0.000 0.000 0.000 0.000 {インスタンス} 69 0.000 0.000 0.000 0.000 {「リスト」オブジェクトのメソッド「追加」} 19 0.000 0.000 0.000 0.000 {「str」オブジェクトの「結合」メソッド} 4 0.000 0.000 0.000 0.000 {時間.時間} 1 0.000 0.000 0.000 0.000 {'unicode' オブジェクトの 'encode' メソッド} 1 0.000 0.000 0.000 0.000 posixpath.py:59(結合) 1 0.000 0.000 0.000 0.000 {posix.stat} 1 0.000 0.000 0.000 0.000 ジェネリックパス.py:38(isdir) 2 0.000 0.000 0.000 0.000 posixpath.py:109(ベース名) 3 0.000 0.000 0.000 0.000 {'str' オブジェクトのメソッド 'rfind'} 1 0.000 0.000 0.000 0.000 posixpath.py:117(ディレクトリ名) 1 0.000 0.000 0.000 0.000 stat.py:40(S_ISDIR) 1 0.000 0.000 0.000 0.000 {'str' オブジェクトの 'startswith' メソッド} 1 0.000 0.000 0.000 0.000 {'str' オブジェクトの 'endswith' メソッド} 1 0.000 0.000 0.000 0.000 {「ファイル」オブジェクトのメソッド「__enter__」} 1 0.000 0.000 0.000 0.000 stat.py:24(S_IFMT) 1 0.000 0.000 0.000 0.000 {「_lsprof.Profiler」オブジェクトのメソッド「無効」}
しかし、search
それでもかなりの時間がかかります (tottime で 10.060)。
誰が問題が何であるかを理解できますか?