1. ホーム
  2. python

[解決済み] Pythonのコードを一行ずつプロファイリングするには?

2022-05-11 19:38:38

質問

cProfile を使って自分のコードをプロファイルしています。また、私は gprof2dot.py を使って結果を可視化しています(少しわかりやすくなります)。

しかし、cProfile (そして私がこれまで見てきた他のほとんどのPythonプロファイラ) は関数呼び出しレベルでのみプロファイルを行うようです。これは、特定の関数が異なる場所から呼び出されたときに混乱を引き起こします。問題の関数が 6 階層の深さにあり、他の 7 つの場所から呼び出される場合、これはさらに悪化します。

行ごとのプロファイリングを取得するにはどうすればよいですか。

この代わりに

function #12, total time: 2.0s

こんな感じでお願いします。

function #12 (called from somefile.py:102) 0.5s
function #12 (called from main.py:12) 1.5s

cProfile は、総時間のうちどれだけが親に転送されるかを示しますが、多くのレイヤーと相互接続された呼び出しがある場合、再びこの接続が失われます。

理想的には、データを解析し、各行に与えられた合計時間と共にソース ファイルを表示する GUI があるとうれしいです。このようなものです。

main.py:

a = 1 # 0.0s
result = func(a) # 0.4s
c = 1000 # 0.0s
result = func(c) # 5.0s

それから、2番目の "func(c)" 呼び出しをクリックして、"func(a)" 呼び出しとは別に、その呼び出しで時間を取っているものを見ることができるようになります。これは意味があるのでしょうか?

どのように解決するのですか?

私は、それが Robert Kern の line_profiler です。 はそのためのものです。 リンク先から。

File: pystone.py
Function: Proc2 at line 149
Total time: 0.606656 s

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
   149                                           @profile
   150                                           def Proc2(IntParIO):
   151     50000        82003      1.6     13.5      IntLoc = IntParIO + 10
   152     50000        63162      1.3     10.4      while 1:
   153     50000        69065      1.4     11.4          if Char1Glob == 'A':
   154     50000        66354      1.3     10.9              IntLoc = IntLoc - 1
   155     50000        67263      1.3     11.1              IntParIO = IntLoc - IntGlob
   156     50000        65494      1.3     10.8              EnumLoc = Ident1
   157     50000        68001      1.4     11.2          if EnumLoc == Ident1:
   158     50000        63739      1.3     10.5              break
   159     50000        61575      1.2     10.1      return IntParIO