Pythonスクリプトのプロファイルをどのように作成できますか?


1283

多くの場合、プロジェクトオイラーやその他のコーディングコンテストの実行時間は最大であるか、特定のソリューションの実行速度が自慢です。Pythonでは、時々アプローチがややこしい-つまり、タイミングコードをに追加する__main__

Pythonプログラムの実行にかかる時間をプロファイルする良い方法は何ですか?


113
プロジェクトオイラープログラムではプロファイリングは必要ありません。1分未満で機能するアルゴリズムがあるか、まったく間違ったアルゴリズムを使用しています。「チューニング」はめったに適切ではありません。一般に、新鮮なアプローチを取る必要があります。
S.Lott、2009

105
S.Lott:プロファイリングは多くの場合、どのサブルーチンが遅いかを判断するのに役立つ方法です。時間がかかるサブルーチンは、アルゴリズムを改善するための優れた候補です。
stalepretzel 2012

回答:


1369

PythonにはcProfileと呼ばれるプロファイラーが含まれています。合計実行時間だけでなく、各関数の時間も個別に示され、各関数が呼び出された回数が示されるため、最適化を行う場所を簡単に決定できます。

次のように、コード内から、またはインタープリターから呼び出すことができます。

import cProfile
cProfile.run('foo()')

さらに便利なことに、スクリプトの実行時にcProfileを呼び出すことができます。

python -m cProfile myscript.py

さらに簡単にするために、「profile.bat」という小さなバッチファイルを作成しました。

python -m cProfile %1

だから私がしなければならないすべては実行されます:

profile euler048.py

そして私はこれを手に入れます:

1007 function calls in 0.061 CPU seconds

Ordered by: standard name
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    1    0.000    0.000    0.061    0.061 <string>:1(<module>)
 1000    0.051    0.000    0.051    0.000 euler048.py:2(<lambda>)
    1    0.005    0.005    0.061    0.061 euler048.py:2(<module>)
    1    0.000    0.000    0.061    0.061 {execfile}
    1    0.002    0.002    0.053    0.053 {map}
    1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler objects}
    1    0.000    0.000    0.000    0.000 {range}
    1    0.003    0.003    0.003    0.003 {sum}

編集:PyCon 2013の優れた動画リソースへのリンクを更新し、「Pythonプロファイリング
もYouTube経由」というタイトルを付け ました


251
また、結果をソートすることも役立ちます。これは-sスイッチで実行できます。例: '-s time'。累積/名前/時間/ファイルの並べ替えオプションを使用できます。
Jiri、

19
また、マジック関数%prun(プロファイル実行)を使用してipythonからcProfileモジュールを使用できることにも注意してください。最初にモジュールをインポートしてから、%prunでmain関数を呼び出します。import euler048; %prun euler048.main()
RussellStewart 14年

53
cProfileダンプ(によって作成されたpython -m cProfile -o <out.profile> <script>)を視覚化するために、RunSnakeRunrunsnake <out.profile>が非常に貴重な方法で呼び出されます。
Lily Chung

13
@NeilGはpython 3 cprofileでも推奨さprofileます。
trichoplax、2015年

17
cProfileダンプを視覚化するために、RunSnakeRunは2011年以降更新されておらず、python3をサポートしていません。代わりにsnakevizを使用してください
Giacomo Tecya Pigani 2017

424

少し前に私はpycallgraphあなたのPythonコードから視覚化を生成することを作りました。編集:この記事の執筆時点で最新のリリースである3.3で動作するように例を更新しました。

pip install pycallgraphインストールとGraphVizをしますが、コマンドラインから実行することができます:

pycallgraph graphviz -- ./mypythonscript.py

または、コードの特定の部分をプロファイルできます。

from pycallgraph import PyCallGraph
from pycallgraph.output import GraphvizOutput

with PyCallGraph(output=GraphvizOutput()):
    code_to_profile()

これらのどちらでも、pycallgraph.png以下の画像のようなファイルが生成されます。

ここに画像の説明を入力してください


43
あなたは通話の量に基づいて着色していますか?その場合は、呼び出し回数が最も多い関数が常に最も時間がかかる関数とは限らないため、時間に基づいて色分けする必要があります。

21
@red色は好きなようにカスタマイズでき、測定ごとに個別にカスタマイズすることもできます。たとえば、通話は赤、時間は青、メモリ使用量は緑です。
2013

2
このエラーが発生するTraceback (most recent call last): /pycallgraph.py", line 90, in generate output.done() File "/net_downloaded/pycallgraph-develop/pycallgraph/output/graphviz.py", line 94, in done source = self.generate() File "/net_downloaded/pycallgraph-develop/pycallgraph/output/graphviz.py", line 143, in generate indent_join.join(self.generate_attributes()), File "/net_downloaded/pycallgraph-develop/pycallgraph/output/graphviz.py", line 169, in generate_attributes section, self.attrs_from_dict(attrs), ValueError: zero length field name in format
Ciasto piekarz 14

3
これを更新して、説明どおりに機能するためにGraphVizをインストールする必要があることを述べました。Ubuntuではこれはちょうどsudo apt-get install graphvizです。
mlissner 2015年

2
これをインストールするには、少し手間がかかりますが、ここでは3つのステップで支援します。1. pip経由でインストールします。2. exe経由でGraphVizをインストールします。3. GraphVizディレクトリへのパス変数を設定します。4.他のすべてのエラーを修正する方法を見つけます。5. pngファイルを保存する場所を見つけますか?
沼地

199

プロファイラーの使用はメインスレッドでのみ(デフォルトで)機能し、他のスレッドを使用しても情報を取得できないことに注意してください。プロファイラーのドキュメントにはまったく記載されていないため、これはちょっとした問題になる可能性があります

スレッドもプロファイリングしたい場合は、ドキュメント内のthreading.setprofile()関数を確認する必要があります。

また、独自のthreading.Threadサブクラスを作成してそれを行うこともできます。

class ProfiledThread(threading.Thread):
    # Overrides threading.Thread.run()
    def run(self):
        profiler = cProfile.Profile()
        try:
            return profiler.runcall(threading.Thread.run, self)
        finally:
            profiler.dump_stats('myprofile-%d.profile' % (self.ident,))

ProfiledThread標準のクラスの代わりにそのクラスを使用します。柔軟性が高まるかもしれませんが、特にクラスを使用しないサードパーティのコードを使用している場合は、その価値があるかどうかはわかりません。


1
ドキュメントにもruncallへの参照はありません。cProfile.pyを見ると、なぜthreading.Thread.run関数もselfも引数として使用するのかわかりません。ここで別のスレッドのrunメソッドへの参照が見られると思っていました。
PypeBros

ドキュメントにはありませんが、モジュールにあります。hg.python.org/cpython/file/6bf07db23445/Lib/cProfile.py#l140を参照してください。これにより、特定の関数呼び出しのプロファイルを作成できます。targetここでは、threading.Thread.run()呼び出しが実行するスレッドの関数のプロファイルを作成します。しかし、答えで述べたように、スレッドをサブクラス化しても、サードパーティのコードでは使用せず、代わりにを使用する価値はありませんthreading.setprofile()
ジョーショー

9
profiler.enable()とprofiler.disable()でコードをラップすることも非常にうまく機能しているようです。これは基本的にruncallが行うことであり、引数や同様のことを強制するものではありません。
PypeBros


1
ジョー、Python 3.4でプロファイラーがasyncioでどのように機能するか知っていますか?
Nick Chammas

149

Python Wikiは、プロファイリングリソースに最適なページです。http//wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code

Pythonのドキュメントと同様に:http : //docs.python.org/library/profile.html

Chris Lawlorが示すように、cProfileは優れたツールであり、画面への印刷に簡単に使用できます。

python -m cProfile -s time mine.py <args>

またはファイルする:

python -m cProfile -o output.file mine.py <args>

PS> Ubuntuを使用している場合は、python-profileをインストールしてください

apt-get install python-profiler 

ファイルに出力すると、次のツールを使用して素晴らしい視覚化を得ることができます

PyCallGraph:コールグラフイメージを作成するツール
インストール:

 pip install pycallgraph

実行:

 pycallgraph mine.py args

見る:

 gimp pycallgraph.png

あなたはPNGファイルを表示したいものを使用することができ、私はGIMPを使用
残念ながら、私は頻繁に取得します

ドット:グラフはcairo-rendererビットマップには大きすぎます。フィットするように0.257079でスケーリング

これにより、画像が小さくなりすぎます。だから私は一般的にsvgファイルを作成します:

pycallgraph -f svg -o pycallgraph.svg mine.py <args>

PS>(ドットプログラムを提供する)graphvizをインストールしてください:

pip install graphviz

@maxy / @quodlibetorを介したgprof2dotを使用した代替グラフ作成:

pip install gprof2dot
python -m cProfile -o profile.pstats mine.py
gprof2dot -f pstats profile.pstats | dot -Tsvg -o mine.svg

12
gprof2dotはこれらのグラフも実行できます。私は出力が少し良いと思います()。
最大

2
OSXを使用している場合もgraphvizが必要です
Vaibhav Mishra 2014年

134

上のMAXYさんのコメント@ この答えは十分に私を助け、私はそれは、独自の答えに値すると思うこと:私はすでにcProfile-生成.pstatsファイルを持っていたし、私が使用して私は、pycallgraphで再実行して、物事にはしたくなかったgprof2dotを、そしてかなり得ましたsvgs:

$ sudo apt-get install graphviz
$ git clone https://github.com/jrfonseca/gprof2dot
$ ln -s "$PWD"/gprof2dot/gprof2dot.py ~/bin
$ cd $PROJECT_DIR
$ gprof2dot.py -f pstats profile.pstats | dot -Tsvg -o callgraph.svg

そしてBLAM!

ドット(pycallgraphが使用するものと同じもの)を使用しているため、出力は似ています。ただし、gprof2dotが失う情報が少ないという印象を受けます。

gprof2dotの出力例


1
良いアプローチです。ChromeなどでSVGを表示し、拡大/縮小できるので、非常にうまく機能します。3行目にはタイプミスがあります:ln -s pwd/gprof2dot/gprof2dot.py $ HOME / bin(または、ほとんどのシェルでln -s $ PWD / gprof2dot / gprof2dot.py〜/ binを使用します-最初のフォーマットとしてアクサングラーブがフォーマットとして使用されますバージョン)。
RichVel 2013年

2
ああ、良い点。私が手lnの引数次の間違ったほぼすべての時間を。
quodlibetor 2013年

7
秘訣は、lnとcpの引数の順序が同じであることを思い出すことです。「file1をfile2またはdir2にコピーするがリンクを作成する」と考えてください
RichVel

それは理にかなっている、私はマンページで「TARGET」の使用が私を投げると思います。
quodlibetor

どうやって角を丸くしたの?読みやすさが向上したように感じます。ボックスの周りに多くのエッジが存在する場合、クールではない醜い鋭いコーナーが表示されます。
Hibou57 2014

78

このトピックを調べていると、SnakeVizという便利なツールに出くわしました。SnakeVizは、Webベースのプロファイリング視覚化ツールです。インストールと使用は非常に簡単です。私がそれを使用する通常の方法は%prun、Stat ファイルを生成してSnakeVizで分析を行うことです。

使用される主なviz手法は、以下に示すサンバーストチャートです。この関数では、関数呼び出しの階層が、円弧のレイヤーと角度幅でエンコードされた時間情報として配置されています。

一番良いのは、チャートを操作できることです。たとえば、ズームインするには、アークをクリックすると、アークとその子孫が新しいサンバーストとして拡大され、詳細が表示されます。

ここに画像の説明を入力してください


1
CodeCabbieの回答には、(短い)インストール手順が含まれており、SnakeVizを(簡単に)使用する方法が示されています。
Oren Milman

ここで私はjupyterノートブックでPythonのためのプロファイリングに使用する方法私見の良いガイドを読んだ:towardsdatascience.com/speed-up-jupyter-notebooks-20716cbe2025
アレクセイMartianov

73

最も簡単かつ最速のすべての時間が起こっている場所を見つける方法。

1. pip install snakeviz

2. python -m cProfile -o temp.dat <PROGRAM>.py

3. snakeviz temp.dat

ブラウザで円グラフを描画します。最大のピースは問題の関数です。とても簡単です。


1
これはとても役に立ちました。ありがとうございました。
jippyjoe4

55

これcProfileはプロファイリングにkcachegrind最適であり、結果を視覚化するのに最適です。pyprof2calltreeハンドルの間でのファイル変換。

python -m cProfile -o script.profile script.py
pyprof2calltree -i script.profile -o script.calltree
kcachegrind script.calltree

必要なツールをインストールするには(少なくともUbuntuでは):

apt-get install kcachegrind
pip install pyprof2calltree

結果:

結果のスクリーンショット


9
Macユーザーは、プロファイリングを成功させるための説明に、brew install qcachegrindそれぞれkcachegrind をインストールし、qcachegrind 実質的です。
Kevin Katzke 2017

私は仕事にそれを得るためにこれをしなければならなかった:export QT_X11_NO_MITSHM=1
Yonatanシムソン

41

また言及する価値があるのは、GUI cProfileダンプビューアRunSnakeRunです。並べ替えて選択できるため、プログラムの関連部分を拡大できます。画像内の長方形のサイズは、かかる時間に比例します。長方形の上にマウスを置くと、その呼び出しがテーブル内とマップ上のすべての場所で強調表示されます。長方形をダブルクリックすると、その部分が拡大されます。誰がその部分を呼び出し、その部分が何を呼び出すかを示します。

説明的な情報は非常に役立ちます。組み込みのライブラリ呼び出しを処理するときに役立つ、そのビットのコードが表示されます。これは、コードを見つけるためのファイルと行を示します。

OPが「プロファイリング」と言ったことを指摘したいが、彼は「タイミング」を意味していたようだ。プロファイルを作成すると、プログラムの実行速度が遅くなることに注意してください。

ここに画像の説明を入力してください


34

優れたプロファイリングモジュールは、line_profiler(スクリプトkernprof.pyを使用して呼び出される)です。こちらからダウンロードできます

私の理解では、cProfileは各関数で費やされた合計時間に関する情報しか提供しません。したがって、コードの個々の行はタイミングが取られません。多くの場合、1行に多くの時間がかかるため、これは科学計算における問題です。また、覚えているように、cProfileは、たとえばnumpy.dotで費やした時間をキャッチできませんでした。


34

最近、Pythonランタイムを視覚化してプロファイルをインポートするためのマグロを作成しました。これはここで役に立ちます。

ここに画像の説明を入力してください

でインストール

pip install tuna

ランタイムプロファイルを作成する

python3 -m cProfile -o program.prof yourfile.py

またはインポートプロファイル(Python 3.7以降が必要)

python3 -X importprofile yourfile.py 2> import.log

次に、ファイルに対してマグロを実行します

tuna program.prof

33

pprofile

line_profiler(すでにここに提示されています)また pprofile、次のように説明されています:

線の細分性、スレッド対応の確定的および統計的な純粋なPythonプロファイラー

line_profilerは純粋なPythonであり、スタンドアロンのコマンドまたはモジュールとして使用でき、さらにで簡単に分析できるcallgrind形式のファイルを生成することもできるので、細分性を提供し[k|q]cachegrindます。

vprof

次のように説明されるPythonパッケージであるvprofもあります。

[...]実行時間やメモリ使用量などのさまざまなPythonプログラムの特性に対して、リッチでインタラクティブな視覚化を提供します。

ヒートマップ


14

すばらしい答えはたくさんありますが、結果のプロファイリングや並べ替えにコマンドラインまたは外部プログラムを使用しています。

コマンドラインに触れたり、何かをインストールしたりせずに、IDE(eclipse-PyDev)で使用できるいくつかの方法が本当にありませんでした。だからここにあります。

コマンドラインなしのプロファイリング

def count():
    from math import sqrt
    for x in range(10**5):
        sqrt(x)

if __name__ == '__main__':
    import cProfile, pstats
    cProfile.run("count()", "{}.profile".format(__file__))
    s = pstats.Stats("{}.profile".format(__file__))
    s.strip_dirs()
    s.sort_stats("time").print_stats(10)

詳細については、ドキュメントまたはその他の回答を参照してください。


たとえば、プロファイルは{map}または{xxx}を出力します。メソッド{xxx}がどのファイルから呼び出されたかを知るにはどうすればよいですか?私のプロファイルは、「zlib.Compress」オブジェクトの{メソッド 'compress'}を出力しますが、ほとんどの時間がかかりますが、zlibは使用していません。どちらが正確なファイルであり、行に長い時間がかかるかを知るにはどうすればよいですか?
machen 2017年

12

マルチスレッドコードが期待どおりに機能しないというジョーショーの回答に続きruncall、cProfile のメソッドは単に実行され、プロファイルされた関数呼び出しself.enable()self.disable()呼び出しているだけであると考えました。既存のコードへの干渉を最小限に抑えます。


3
素晴らしいヒント!cprofile.pyのソースコードをざっと見ると、まさにそれが何をするのかruncall()がわかります。より具体的には、を使用してProfileインスタンスを作成した後prof = cprofile.Profile()、すぐにを呼び出しprof.disable()、プロファイルを作成するコードのセクションを追加prof.enable()してprof.disable()呼び出します。
martineau 2012年

これは非常に便利ですが、実際に有効化と無効化の間にあるコードはプロファイリングされていないようで、それが呼び出す関数のみがプロファイリングされています。これは正しいですか?そのコードを関数呼び出しにラップして、print_stats()の数値にカウントする必要があります。
ボブスタイン

10

Virtaalのソースには、(特定のメソッド/関数の場合でも)プロファイリングを非常に簡単にすることができる非常に便利なクラスとデコレータがあります。その後、出力はKCacheGrindで非常に快適に表示できます。


1
この宝石をありがとう。参考:これは、任意のコードでスタンドアロンモジュールとして使用できます。Virtaalコードベースは必要ありません。ファイルをprofiling.pyに保存し、profile_func()をインポートするだけです。@profile_func()を、プロファイリングとビオラに必要な関数のデコレーターとして使用します。:)
Amjith、2011年

9

cProfileは迅速なプロファイリングに最適ですが、ほとんどの場合、エラーで終了していました。関数runctxは、環境と変数を正しく初期化することでこの問題を解決します。誰かに役立つことを願っています。

import cProfile
cProfile.runctx('foo()', None, locals())

7

累積プロファイラーを作成する場合は、関数を数回続けて実行し、結果の合計を監視します。

このcumulative_profilerデコレータを使用できます:

それはpython> = 3.6固有ですがnonlocal、古いバージョンで動作するように削除できます。

import cProfile, pstats

class _ProfileFunc:
    def __init__(self, func, sort_stats_by):
        self.func =  func
        self.profile_runs = []
        self.sort_stats_by = sort_stats_by

    def __call__(self, *args, **kwargs):
        pr = cProfile.Profile()
        pr.enable()  # this is the profiling section
        retval = self.func(*args, **kwargs)
        pr.disable()

        self.profile_runs.append(pr)
        ps = pstats.Stats(*self.profile_runs).sort_stats(self.sort_stats_by)
        return retval, ps

def cumulative_profiler(amount_of_times, sort_stats_by='time'):
    def real_decorator(function):
        def wrapper(*args, **kwargs):
            nonlocal function, amount_of_times, sort_stats_by  # for python 2.x remove this row

            profiled_func = _ProfileFunc(function, sort_stats_by)
            for i in range(amount_of_times):
                retval, ps = profiled_func(*args, **kwargs)
            ps.print_stats()
            return retval  # returns the results of the function
        return wrapper

    if callable(amount_of_times):  # incase you don't want to specify the amount of times
        func = amount_of_times  # amount_of_times is the function in here
        amount_of_times = 5  # the default amount
        return real_decorator(func)
    return real_decorator

関数のプロファイリング baz

import time

@cumulative_profiler
def baz():
    time.sleep(1)
    time.sleep(2)
    return 1

baz()

baz 5回実行してこれを印刷しました:

         20 function calls in 15.003 seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       10   15.003    1.500   15.003    1.500 {built-in method time.sleep}
        5    0.000    0.000   15.003    3.001 <ipython-input-9-c89afe010372>:3(baz)
        5    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

回数の指定

@cumulative_profiler(3)
def baz():
    ...

7

これらのすべての豪華なUIがインストールまたは実行に失敗した場合のターミナルのみの(そして最も単純な)ソリューション:完全に
無視cProfileしてに置き換えるとpyinstrument、実行直後に呼び出しのツリーが収集されて表示されます。

インストール:

$ pip install pyinstrument

プロファイルと表示結果:

$ python -m pyinstrument ./prog.py

python2および3で動作します。

[編集]コードの一部のみをプ​​ロファイリングするためのAPIのドキュメントは、ここにあります


6

私の方法は、yappi(https://github.com/sumerc/yappi)を使用することです。これは、RPCサーバーと組み合わせると特に便利です。デバッグだけでも、たとえば次のように、プロファイリング情報を開始、停止、印刷するメソッドを登録できます。

@staticmethod
def startProfiler():
    yappi.start()

@staticmethod
def stopProfiler():
    yappi.stop()

@staticmethod
def printProfiler():
    stats = yappi.get_stats(yappi.SORTTYPE_TTOT, yappi.SORTORDER_DESC, 20)
    statPrint = '\n'
    namesArr = [len(str(stat[0])) for stat in stats.func_stats]
    log.debug("namesArr %s", str(namesArr))
    maxNameLen = max(namesArr)
    log.debug("maxNameLen: %s", maxNameLen)

    for stat in stats.func_stats:
        nameAppendSpaces = [' ' for i in range(maxNameLen - len(stat[0]))]
        log.debug('nameAppendSpaces: %s', nameAppendSpaces)
        blankSpace = ''
        for space in nameAppendSpaces:
            blankSpace += space

        log.debug("adding spaces: %s", len(nameAppendSpaces))
        statPrint = statPrint + str(stat[0]) + blankSpace + " " + str(stat[1]).ljust(8) + "\t" + str(
            round(stat[2], 2)).ljust(8 - len(str(stat[2]))) + "\t" + str(round(stat[3], 2)) + "\n"

    log.log(1000, "\nname" + ''.ljust(maxNameLen - 4) + " ncall \tttot \ttsub")
    log.log(1000, statPrint)

次に、プログラムが機能するときに、startProfilerRPCメソッドを呼び出していつでもプロファイラーを開始し、呼び出してprintProfiler(またはrpcメソッドを変更して呼び出し元に返すように)プロファイリング情報をログファイルにダンプし、そのような出力を取得できます。

2014-02-19 16:32:24,128-|SVR-MAIN  |-(Thread-3   )-Level 1000: 
name                                                                                                                                      ncall     ttot    tsub
2014-02-19 16:32:24,128-|SVR-MAIN  |-(Thread-3   )-Level 1000: 
C:\Python27\lib\sched.py.run:80                                                                                                           22        0.11    0.05
M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\pyAheadRpcSrv\xmlRpc.py.iterFnc:293                                                22        0.11    0.0
M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\serverMain.py.makeIteration:515                                                    22        0.11    0.0
M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\pyAheadRpcSrv\PicklingXMLRPC.py._dispatch:66                                       1         0.0     0.0
C:\Python27\lib\BaseHTTPServer.py.date_time_string:464                                                                                    1         0.0     0.0
c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\_psmswindows.py._get_raw_meminfo:243     4         0.0     0.0
C:\Python27\lib\SimpleXMLRPCServer.py.decode_request_content:537                                                                          1         0.0     0.0
c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\_psmswindows.py.get_system_cpu_times:148 4         0.0     0.0
<string>.__new__:8                                                                                                                        220       0.0     0.0
C:\Python27\lib\socket.py.close:276                                                                                                       4         0.0     0.0
C:\Python27\lib\threading.py.__init__:558                                                                                                 1         0.0     0.0
<string>.__new__:8                                                                                                                        4         0.0     0.0
C:\Python27\lib\threading.py.notify:372                                                                                                   1         0.0     0.0
C:\Python27\lib\rfc822.py.getheader:285                                                                                                   4         0.0     0.0
C:\Python27\lib\BaseHTTPServer.py.handle_one_request:301                                                                                  1         0.0     0.0
C:\Python27\lib\xmlrpclib.py.end:816                                                                                                      3         0.0     0.0
C:\Python27\lib\SimpleXMLRPCServer.py.do_POST:467                                                                                         1         0.0     0.0
C:\Python27\lib\SimpleXMLRPCServer.py.is_rpc_path_valid:460                                                                               1         0.0     0.0
C:\Python27\lib\SocketServer.py.close_request:475                                                                                         1         0.0     0.0
c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\__init__.py.cpu_times:1066               4         0.0     0.0 

これは短いスクリプトにはあまり役立ちませんが、特にprintProfilerさまざまなプログラムの使用シナリオなどのプロファイルを作成して比較するために時間をかけて複数回呼び出すことができるメソッドであれば、サーバータイプのプロセスを最適化するのに役立ちます。

新しいバージョンのyappiでは、次のコードが機能します。

@staticmethod
def printProfile():
    yappi.get_func_stats().print_all()

とんでもないやっぴと名付けるべきではないでしょうか。
Therealstubot 14

残念ながら、上記のコードはpypyでは使用できないバージョン0.62でのみ機能します。モジュールはここから入手できる0.62ソースからコンパイルする必要があります:github.com/nirs/yappi/releasesまたはその目的のためにフォークされたレポでウィンドウ用に作成したビルドを使用するgithub.com/Girgitt/yappi/releases
Mr. Girgitt

バージョン1.0との互換性は、少なくとも印刷出力のために、printProfiler関数を変更することにより、簡単に提供できます def printProfiler(): if not yappi_available: return stats = yappi.get_func_stats() stats.print_all(columns={0:("name",90), 1:("ncall", 5), 2:("tsub", 8), 3:("ttot", 8), 4:("tavg",8)}) 。 )
ギルギット氏19年

4

Pythonでプロファイリングを処理する新しいツールはPyVmMonitorです:http ://www.pyvmmonitor.com/

それは次のようないくつかのユニークな機能を備えています

  • 実行中の(CPython)プログラムにプロファイラーを接続する
  • Yappi統合によるオンデマンドプロファイリング
  • 別のマシンのプロファイル
  • 複数のプロセスのサポート(マルチプロセッシング、django ...)
  • ライブサンプリング/ CPUビュー(時間範囲選択あり)
  • cProfile /プロファイル統合による確定的プロファイリング
  • 既存のPStats結果を分析する
  • DOTファイルを開く
  • プログラムによるAPIアクセス
  • メソッドまたはラインでサンプルをグループ化
  • PyDevの統合
  • PyCharmの統合

注:商用ですが、オープンソースの場合は無料です。


4

gprof2dot_magic

gprof2dotPythonステートメントをJupyterLabまたはJupyter NotebookのDOTグラフとしてプロファイルするためのマジック関数。

ここに画像の説明を入力してください

GitHubリポジトリ:https : //github.com/mattijn/gprof2dot_magic

インストール

Pythonパッケージがあることを確認してくださいgprof2dot_magic

pip install gprof2dot_magic

その依存関係gprof2dotgraphviz同様にインストールされます

使用法

マジック機能を有効にするには、まずgprof2dot_magicモジュールをロードします

%load_ext gprof2dot_magic

次に、任意の行ステートメントをDOTグラフとしてプロファイルします。

%gprof2dot print('hello world')

ここに画像の説明を入力してください


3

Pythonスクリプトが何をしているのか知りたいですか?検査シェルに入ります。Inspect Shellを使用すると、実行中のスクリプトを中断することなく、グローバルを印刷/変更して関数を実行できます。オートコンプリートとコマンド履歴が追加されました(Linuxのみ)。

Inspect Shellはpdbスタイルのデバッガではありません。

https://github.com/amoffat/Inspect-Shell

あなたはそれ(そしてあなたの腕時計)を使うことができます。


3

https://stackoverflow.com/a/582337/1070617に追加するには、

私は、cProfileを使用してその出力を簡単に表示できるようにするこのモジュールを作成しました。詳細:https : //github.com/ymichael/cprofilev

$ python -m cprofilev /your/python/program
# Go to http://localhost:4000 to view collected statistics.

収集された統計を理解する方法については、http//ymichael.com/2014/03/08/profiling-python-with-cprofile.htmlも参照してください。


3

プロファイリングで確認したい内容によって異なります。単純な時間メトリックは(bash)で指定できます。

time python python_prog.py

「/ usr / bin / time」でも、「-verbose」フラグを使用して詳細なメトリックを出力できます。

各関数によって与えられた時間メトリックをチェックし、関数に費やされた時間をよりよく理解するには、Pythonで組み込みのcProfileを使用できます。

パフォーマンスのようなより詳細なメトリックに入ると、時間だけがメトリックではありません。メモリ、スレッドなどについて心配することができ
ます。プロファイリングオプション:
1. line_profilerは、行ごとにタイミングメトリックを見つけるために一般的に使用される別のプロファイラーです。
2. memory_profilerは、メモリ使用量をプロファイルするツールです。
3. heapy(プロジェクトGuppyから)ヒープ内のオブジェクトがどのように使用されるかをプロファイルします。

これらは、私がよく使用する一般的なものです。しかし、さらに詳しく知りたい場合 は、この本を読んでみてください。これは、パフォーマンスを念頭に置いて始めることについてはかなり良い本です。CythonおよびJIT(ジャストインタイム)コンパイル済みpythonの使用に関する高度なトピックに進むことができます。


2

austinのような統計プロファイラーを使用すると、インストルメンテーションは不要になります。つまり、Pythonアプリケーションからプロファイリングデータを簡単に取得できます。

austin python3 my_script.py

生の出力はあまり役に立ちませんが、それをflamegraph.pl にパイプして、時間(マイクロ秒単位で測定)が費やされている場所の内訳を示すデータのフレームグラフ表現を取得できます。

austin python3 my_script.py | flamegraph.pl > my_script_profile.svg

2

IPythonノートブックでプロファイルの統計をすばやく取得するため。line_profilermemory_profilerをノートブックに直接埋め込むことができます。

別の便利なパッケージはPymplerです。これは、クラス、オブジェクト、関数、メモリリークなどを追跡できる強力なプロファイリングパッケージです。以下の例では、ドキュメントが添付されています。

それを得る!

!pip install line_profiler
!pip install memory_profiler
!pip install pympler

それをロードしてください!

%load_ext line_profiler
%load_ext memory_profiler

これを使って!


%時間

%time print('Outputs CPU time,Wall Clock time') 
#CPU times: user 2 µs, sys: 0 ns, total: 2 µs Wall time: 5.96 µs

与える:

  • CPU時間:CPUレベルの実行時間
  • sys時間:システムレベルの実行時間
  • 合計:CPU時間+システム時間
  • ウォールタイム:Wall Clock Time

%timeit

%timeit -r 7 -n 1000 print('Outputs execution time of the snippet') 
#1000 loops, best of 7: 7.46 ns per loop
  • ループ(n)回の実行回数(r)のうち、最高の時間を提供します。
  • システムキャッシングに関する詳細を出力します。
    • コードスニペットが複数回実行されると、システムはいくつかの操作をキャッシュし、それらを再度実行しないため、プロファイルレポートの正確性が損なわれる可能性があります。

%prun

%prun -s cumulative 'Code to profile' 

与える:

  • 関数呼び出しの数(ncalls)
  • 関数呼び出しごとにエントリがあります(個別)
  • 呼び出しごとの所要時間(呼び出しごと)
  • その関数呼び出しまでの経過時間(cumtime)
  • などと呼ばれるfunc / moduleの名前...

累積プロファイル


%memit

%memit 'Code to profile'
#peak memory: 199.45 MiB, increment: 0.00 MiB

与える:

  • メモリ使用量

%lprun

#Example function
def fun():
  for i in range(10):
    print(i)

#Usage: %lprun <name_of_the_function> function
%lprun -f fun fun()

与える:

  • 行ごとの統計

LineProfile


sys.getsizeof

sys.getsizeof('code to profile')
# 64 bytes

オブジェクトのサイズをバイト単位で返します。


pymplerのasizeof()

from pympler import asizeof
obj = [1,2,("hey","ha"),3]
print(asizeof.asizeof(obj,stats=4))

pympler.asizeofを使用して、特定のPythonオブジェクトが消費するメモリ量を調査できます。sys.getsizeofとは対照的に、asizeofはオブジェクトを再帰的にサイズ設定します

pympler.asizeof


pymplerからのトラッカー

from pympler import tracker
tr = tracker.SummaryTracker()
def fun():
  li = [1,2,3]
  di = {"ha":"haha","duh":"Umm"}
fun()
tr.print_diff()

関数の寿命を追跡します。

トラッカー出力

Pymplerパッケージは、コードをプロファイルするための非常に多くの高ユーティリティ関数で構成されています。ここではすべてをカバーすることはできません。詳細なプロファイルの実装については、添付のドキュメントを参照してください。

Pymplerのドキュメント


1

と呼ばれる統計プロファイラもありstatprofます。これはサンプリングプロファイラーであるため、コードに最小限のオーバーヘッドを追加し、(関数ベースだけでなく)行ベースのタイミングを提供します。ゲームなどのソフトリアルタイムアプリケーションに適していますが、cProfileよりも精度が低い場合があります。

pypiバージョンは少し古いので、gitリポジトリをpip指定しインストールできます

pip install git+git://github.com/bos/statprof.py@1a33eba91899afe17a8b752c6dfdec6f05dd0c01

次のように実行できます。

import statprof

with statprof.profile():
    my_questionable_function()

https://stackoverflow.com/a/10333592/320036も参照してください


1

私は、pypref_timeからインスピレーションを得た独自のプロファイラーを開発しました。

https://github.com/modaresimr/auto_profiler

デコレータを追加すると、時間のかかる関数のツリーが表示されます

@Profiler(depth=4, on_disable=show)

Install by: pip install auto_profiler

import time # line number 1
import random

from auto_profiler import Profiler, Tree

def f1():
    mysleep(.6+random.random())

def mysleep(t):
    time.sleep(t)

def fact(i):
    f1()
    if(i==1):
        return 1
    return i*fact(i-1)


def show(p):
    print('Time   [Hits * PerHit] Function name [Called from] [Function Location]\n'+\
          '-----------------------------------------------------------------------')
    print(Tree(p.root, threshold=0.5))

@Profiler(depth=4, on_disable=show)
def main():
    for i in range(5):
        f1()

    fact(3)


if __name__ == '__main__':
    main()

出力例


Time   [Hits * PerHit] Function name [Called from] [function location]
-----------------------------------------------------------------------
8.974s [1 * 8.974]  main  [auto-profiler/profiler.py:267]  [/test/t2.py:30]
├── 5.954s [5 * 1.191]  f1  [/test/t2.py:34]  [/test/t2.py:14]
   └── 5.954s [5 * 1.191]  mysleep  [/test/t2.py:15]  [/test/t2.py:17]
       └── 5.954s [5 * 1.191]  <time.sleep>
|
|
|   # The rest is for the example recursive function call fact
└── 3.020s [1 * 3.020]  fact  [/test/t2.py:36]  [/test/t2.py:20]
    ├── 0.849s [1 * 0.849]  f1  [/test/t2.py:21]  [/test/t2.py:14]
       └── 0.849s [1 * 0.849]  mysleep  [/test/t2.py:15]  [/test/t2.py:17]
           └── 0.849s [1 * 0.849]  <time.sleep>
    └── 2.171s [1 * 2.171]  fact  [/test/t2.py:24]  [/test/t2.py:20]
        ├── 1.552s [1 * 1.552]  f1  [/test/t2.py:21]  [/test/t2.py:14]
           └── 1.552s [1 * 1.552]  mysleep  [/test/t2.py:15]  [/test/t2.py:17]
        └── 0.619s [1 * 0.619]  fact  [/test/t2.py:24]  [/test/t2.py:20]
            └── 0.619s [1 * 0.619]  f1  [/test/t2.py:21]  [/test/t2.py:14]

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.