6

cProfilePython スクリプトのプロファイリングに使用し始めています。私は非常に奇妙なことに気づきました。

スクリプトの実行時間を測定するために使用timeすると、4.3 秒かかります。

私が使っpython -m cProfile script.pyた時は7.3秒かかりました。

コード内でプロファイラーを実行する場合:

import profile
profile.run('main()')

63秒かかります!!

cProfileプロファイリングを追加するときにもう少し時間がかかる理由は理解できますが、外部から使用する場合とコードの一部として使用する場合で、このような違いがあるのはなぜですか? を使用すると時間がかかるのには理由がありますprofile.runか?

4

1 に答える 1

6

奇妙なことに、あなたが見ているのは予期された動作です。Python ドキュメントのプロファイラー セクションの紹介でprofilecProfile. あなたが見ている違いは、呼び出し方ではなく、使用しているライブラリにあります。次のスクリプトを検討してください。

import profile
import cProfile

def nothing():
    return

def main():
    for i in xrange(1000):
        for j in xrange(1000):
            nothing()

    return

cProfile.run('main()')
profile.run('main()')

show mainからの出力はcProfile、実行に約 0.143 秒かかりますが、profile亜種は 1.645 秒と報告されており、これは約 11.5 倍長くなります。

ここで、スクリプトを次のように変更しましょう。

def nothing():
    return

def main():
    for i in xrange(1000):
        for j in xrange(1000):
            nothing()

    return

if __name__ == "__main__":
    main()

そして、プロファイラーでそれを呼び出します:

python -m プロファイル test_script.py

メインの実行に 1.662 秒を報告します。

python -m cProfile test_script.py

メインの実行に 0.143 秒を報告します。

cProfileこれは、プロファイラーを起動する方法が、 と の間に見られた不一致とは何の関係もないことを示していますprofile。この違いは、2 つのプロファイラーが関数呼び出しや戻り値などの「イベント」を処理する方法によって発生します。どちらの場合も、実行中のコード全体にソフトウェア フックがあり、コールバックをトリガーしてこれらのイベントを追跡し、イベントのカウンターを更新したり、タイマーを開始または停止したりします。ただし、profileモジュールはこれらすべてのイベントを Pythonでネイティブに処理します。つまり、インタープリターはコードを離れ、コールバックを実行し、戻ってコードを続行する必要があります。

cProfile(プロファイリング コールバックを実行する) でも同じことが発生する必要がありますが、コールバックが C で記述されているため、はるかに高速です。2 つのモジュール ファイルprofile.pycProfile.pyを見ると、いくつかの違いが示されます。

  1. profile.pyは 610 行ですが、cProfile.pyはわずか 199 行です。ほとんどの関数は C で処理されます。
  2. profile.pyは主に Python ライブラリを使用しますが、cProfile.pyは C コード ファイルである「_lsprof」をインポートします。ソースはここで見ることができます。
  3. profile.pyProfileクラスは他のどのクラスからも継承されませんが (111 行目)、cProfile.pyのクラス(66 行目)は C ソース ファイルに実装されている から継承されます。Profile_lsprof.Profiler

ドキュメントcProfileに記載されているように、ほとんどがCで実装されているため、すべてが高速であるため、一般的にはこれが適しています。

余談ですが、profileキャリブレーションを行うことで のパフォーマンスを向上させることができます。それを行う方法の詳細は、ドキュメントで入手できます。これらすべてがどのように/なぜこのようになっているのかについての詳細は、決定論的プロファイリング制限に関する Python ドキュメント セクションにあります。

TL;DR

cProfileその名前が示すように、ほとんどが C で実装されているため、はるかに高速です。これはprofile、ネイティブ Python ですべてのプロファイリング コールバックを処理する必要があるモジュールとは対照的です。プロファイラーをコマンド ラインから呼び出すか、スクリプト内で手動で呼び出すかは、2 つのモジュール間の時間差に影響しません。

于 2014-08-15T21:41:42.060 に答える