5

pyre2( https://github.com/axiak/pyre2 )を使用すると、パフォーマンスの問題 (マッチング時間) が発生しました。

私は3つのプログラムを持っています:

  1. 組み込みの re モジュールを使用した純粋な Python: https://gist.github.com/1873402

  2. Pyre2 を使用した Python: https://gist.github.com/1873402。(コードの大部分は第 1 のプログラムと同じです。組み込みの re を使用する場合を除いて、utf-8 文字列を unicode にデコードします。これは pyre2 を使用する場合には必要ありません)

  3. 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)。

誰が問題が何であるかを理解できますか?

4

1 に答える 1