4

PythonやMatlabで利用できるような言語のラインプロファイラーを作成するために何が必要かを判断しようとしています。

「ラインプロファイラー」を解釈する素朴な方法は、すべての行の周りに時間ログを挿入できると想定することですが、行の定義は、パーサーが空白を処理する方法に依存します。これは最初の問題にすぎません。解析ツリーを使用して、個々のノードの周りにタイミングを挿入する必要があるようです。

この結論は正しいですか?ラインプロファイラーには解析ツリーが必要ですか?必要なのは(時間ログを超えて)それだけですか?


更新1:質問がまだ解決されていないため、これに報奨金を提供します。

更新2:この質問に答えるのに役立つ場合に備えて、よく知られているPythonラインプロファイラーへのリンクを次に示します。構文解析に関連する動作の先頭または末尾をまだ作成できていません。Matlabプロファイラーのコードにアクセスできないのではないかと思います。

また、入力コードを手動で装飾すると、解析ツリーが不要になると言えますが、これは自動プロファイラーではありません。

更新3:この質問は言語に依存しませんが、R用のそのようなツールを作成することを考えているために発生しました(存在し、見つからない場合を除く)。

更新4:ラインプロファイラーとコールスタックプロファイラーの使用について-コールスタックプロファイラー(この場合)の使用に関するこの投稿Rprof()は、ラインプロファイラーを介して物事を直接分析するのではなく、コールスタックを操作するのが面倒な理由を示しています。

4

2 に答える 2

3

ラインプロファイラーとは、各ライン内で費やされた時間 (つまり、計測) を測定するものであるように聞こえます。時間という言葉が実際の時計の時間であることを願っています。なぜなら、実際の大きなソフトウェアでは、CPU 時間だけを見ると、多くの時間を逃すことになるからです。

それを行う別の方法は、 ZoomおよびLTProfプロファイラーのように、実時間でのスタック サンプリングです。スタック サンプルのすべての行は、デバッガーと同じ方法でマップまたは pdb ファイルのみを使用してコード行にローカライズできるため、ソースを解析または変更する必要はありません。

コード行にかかる時間の割合は、単純にそれを含むスタック サンプルの割合です。ライン レベルで作業しているため、排他的 (自己) 時間と包括的時間を区別する必要はありません。これは、別の関数の呼び出し、ブラインド システム関数の呼び出し、または単なるマイクロコードの呼び出しであるかどうかに関係なく、回線のアクティブな時間の割合が重要であるためです。

絶対時間ではなくパーセントを見る利点は、サンプリング自体や他のプロセスとの競合によってアプリが遅くなることを心配する必要がないことです。多くの。

また、再帰について心配する必要はありません。コード行が再帰関数内にあり、サンプルに複数回出現する場合、それは問題ありません。ラインを含む 1 つのサンプルとしてカウントされます。OK である理由は、そのコード行が何らかの方法で (削除するなどして) 時間がかからないようにすることができれば、そのサンプルは発生しなかったからです。したがって、その行を含むサンプルはサンプル セットから削除され、プログラムの合計時間は削除されたサンプルの割合と同じ量だけ減少します。それは再帰に関係なくです。

また、コード行が実行された回数を数える必要もありません。最適化する必要があるコードを見つけるのに重要なのは、そのコードがアクティブになっている時間の割合だからです。

これらの問題について詳しく説明します。

于 2011-09-05T20:56:29.627 に答える
3

はい、解析ツリー (およびソース) が必要です。「行」と有効なステートメントを構成するものを他にどのように知ることができますか?

ただし、実用的な単純化は、「行プロファイラー」の代わりに「ステートメント プロファイラー」になる可能性があります。R では、解析ツリーはすぐに利用できる:body(theFunction)であるため、各ステートメントの周りに測定コードを挿入するのはかなり簡単なはずです。さらに作業を行うと、同じ行に属するステートメントのグループの周りに挿入できます。

R では、通常、ファイルからロードされた関数の本体には、srcref各「行」(実際には各ステートメント) のソースをリストする属性もあります。

これがサンプル関数です(「example.R」に入れられます):

f <- function(x, y=3)
{
    a <- 0; a <- 1  # Two statements on one line
    a <- (x + 1) *  # One statement on two lines
        (y + 2)

    a <- "foo       
        bar"        # One string on two lines
}

次にRで:

source("example.R")
dput(attr(body(theFunction), "srcref"))

この行/列情報を出力します:

list(structure(c(2L, 1L, 2L, 1L, 1L, 1L, 2L, 2L), srcfile = <environment>, class = "srcref"), 
    structure(c(3L, 2L, 3L, 7L, 9L, 14L, 3L, 3L), srcfile = <environment>, class = "srcref"), 
    structure(c(3L, 10L, 3L, 15L, 17L, 22L, 3L, 3L), srcfile = <environment>, class = "srcref"), 
    structure(c(4L, 2L, 5L, 15L, 9L, 15L, 4L, 5L), srcfile = <environment>, class = "srcref"), 
    structure(c(7L, 2L, 8L, 6L, 9L, 20L, 7L, 8L), srcfile = <environment>, class = "srcref"))

ご覧のとおり (各構造の最後の 2 つの数字は開始/終了行です)、式a <- 0a <- 1マップは同じ行に...

幸運を!

于 2011-09-28T19:23:24.930 に答える