Pythonプロファイリングとデバッグ

少し前に、「 Djangoのプロファイリングとデバッグ 」について話しました。 スピーチの後、私は多くの質問を(個人的にもメールでも)受けました。新しい知り合いが2人、バーに行き、重要なプログラミングの問題をグラスの素晴らしいエールで議論しました。今まで多くの人とコミュニケーションをとっています。



プレゼンテーションは大きな関心を呼び、同僚との会話によりプレゼンテーションのいくつかの側面を再考し、迷惑な間違いを修正することができたため、レポートと私の考えを記事の形で作成することにしました。 これにより、関心のある関係者のより広いサークルでトピックに慣れることができます。さらに、Habrは、提案された資料にコメントし、興味深い対話者と通信するための理想的なプラットフォームを提供します。



たくさんの資料があり、記事は巨大だったので、いくつかの部分に分けることにしました。





はじめに



まず、定義を処理する必要があります。 ウィキペディアで読む



プロファイリング-さらなる最適化を目的として、プログラムの特性を収集します。



そのため、プロファイリングには動作するプログラムが必要です。動作するプログラムは、期待どおりに動作しません。動作が遅すぎるか、リソースを消費しすぎています。



プログラムのどのような特徴を収集できますか?



もちろん、プロジェクトを顕微鏡下で詳細に研究し、各命令を分析し、すべてを徹底的に研究することは必ずしも理にかなっていますが、何を、どのように、どこで見ることができるかを知ることは有用で必要です。



「最適化」の概念を定義しましょう。 ウィキペディアは次のように語っています。



最適化は、効率を改善するためのシステムの修正です。



「効率」の概念は非常に曖昧であり、目標に直接依存します。たとえば、プログラムが可能な限り高速に動作する場合もあれば、速度を無視できる場合もあり、RAMやその他のリソース(ディスクなど)を保存することがはるかに重要です。 フレデリックブルックスが正しく言ったように 、「特効薬は存在しません」。



明らかに、プログラムの無限の最適化に取り組むことができます。かなり複雑なプロジェクトでは、常に改善できるボトルネックがあるため、時間通りに停止できることが重要です。 ほとんどの場合(例外は非常にまれであり、実際の生活よりも民間伝承に関連しています)、たとえば、3日間の労働時間を費やして速度を5%上げることは意味がありません。



一方、ドナルドクヌースがかつて言っていたように、「時期尚早な最適化はすべての病気の根源です。」



この引用なしで最適化に関する記事は何ですか? その著者はドナルド・クヌースであると多くの人が信じていますが、ドナルド自身はアンソニー・ホアが最初にそれを話したと主張しています。 一方、アンソニーはロックを解除し、発言を「パブリックドメイン」と見なすことを提案します。



プログラムの作業で私たちにまったく合わないものと達成したい目標を明確に理解することは重要ですが、これはすべてが遅くなり始めたときにプロファイリングとその後の最適化を行う必要があるという意味ではありません。 優れたプログラマーは、自分が書いたプログラムがどのように感じ、危機的な状況(Habraエフェクトなど)でのパフォーマンスを予測するかを常に知っています。



もう1つ重要な点に注意します。多くの場合、最適化にはコードの可読性の大幅な低下が伴います。 可能な場合はこれを避け、重要な場所で読みにくいコードを書く必要がある場合は、怠けずに、その作業の詳細な説明をコメントに残してください。 あなたの同僚はあなたに感謝します、そして、あなたがあなたがしばらく後にこれらのラインに戻るとき、あなた自身は驚くほど洞察力があると思うでしょう。



上記で述べたように、すべてがタスクに非常に依存しており、各ケースを個別に分析する必要があるため、最適化の問題についてはもう触れません。 プログラムの問題領域の検出に重点を置いています。



プロファイリングのアプローチ



少なくとも3つのプロファイリングアプローチがあります。



注視法 (および関連する「 槍法 」)を使用すると、すべてが明確になります。 テキストエディタの前に座ってコードを開き、問題がどこにあるかを考え、修正を試み、結果を確認し、ロールバックします。 そして、まれな場合( または開発者の最高の資格を持つ場合)にのみ、この方法は効果的です。



この方法の長所と短所:

+特別な知識とスキルは不要

-人件費と結果の評価が難しい



ボトルネックについて合理的な仮定があり、仮説を確認または反論する必要がある場合、 手動プロファイリングを使用すると便利です。 または、最初の方法とは異なり、最適化の結果の数値インジケーターを取得する必要がある場合(たとえば、関数は946ミリ秒で実行され、73ミリ秒で動作し始め、コードは13倍加速されました)。



このメソッドの本質は次のとおりです。プログラムの論争の的となっている部分を実行する前に、現在のシステム時間(マイクロ秒まで)を変数に保存してから、再び現在の時間を取得し、保存した変数の値を減算します。 分析されたコードの実行時間を取得します(十分なエラーがあります)。 信頼できる結果を得るには、N回繰り返して平均値を取得します。



この方法の長所と短所:

+非常にシンプルなアプリケーション

+生産限定

-プロジェクトへの「エイリアン」コードの挿入

-常に使用できるとは限らない

-分析されたセクションの実行時間を除き、プログラムに関する情報はありません

-結果の分析が難しい場合があります



ツールを使用したプロファイリングは、(何らかの理由で)プログラムが正常に機能しない理由がわからない場合や、手動プロファイリングを使用して結果を分析するのが面倒な場合に役立ちます。 次のセクションでツールについて詳しく説明します。



選択したアプローチに関係なく、開発者の頭脳が開発者のメインツールであることに変わりはありません。 単一のプログラムではありません( まだ(?)

ねえ、あなたはプロジェクト/ app.pyファイルの行619でナンセンスを得ました その機能をループから外すと、あなたは幸せになります。 それでも、キャッシュを使用してCの計算関数を書き換えると、パフォーマンスは平均18倍になります!



ツールは何ですか



ツールには2つのタイプがあります(実際、分類と用語にはさらに多くのオプションがありますが、2つに制限します)。



残念ながら、「決定論的」プロファイラのロシア語で美しい名前を思い付くことができなかったため、「イベント」という言葉を使用します。 誰かがコメントで私を修正してくれたら感謝します。



ほとんどの開発者はイベントプロファイラーにしか精通しておらず、統計プロファイラーが最初に登場したという事実は彼らにとって大きな驚きです。前世紀の70年代初頭、 IBM / 360およびIBM / 370コンピュータープログラマーは、 プログラムステータスワードの現在の値を記録するタイマー割り込みを設定しました(PSW)。 保存されたデータをさらに分析することで、プログラムの問題領域を特定できました。



最初のイベントプロファイラーは、同じ70年代の終わりに登場し、Unix prof OSのユーティリティであり、すべてのプログラム機能の実行時間を示しました。 数年後(1982年)、 gprofユーティリティが登場し、関数呼び出しのグラフを表示するようになりました。



統計プロファイラー



統計プロファイラの動作原理は単純です。指定された(十分に小さい)間隔で、実行中の現在の命令へのポインタが取得され、後で調査するためにこの情報(「サンプル」)が保存されます。 次のようになります。



関数bar()は 、関数foo()baz()およびある種の匿名命令よりもほぼ2.5倍長く実行されたことがわかります。



統計プロファイラーの欠点の1つは、プログラムの動作に関する適切な統計を取得するために、できるだけ短い間隔でできるだけ多くの(理想的には、無限の)測定を実行する必要があることです。 そうしないと、一部のコールがまったく分析されない場合があります。



たとえば、図から、名前のない関数が選択に含まれなかったことがわかります。



分析された関数のリアルタイムを評価することも困難です。 関数foo()が十分に迅速に実行されるが、非常に頻繁に呼び出される状況を考えます。



foo()関数は非常に長い時間がかかるが、一度だけ呼び出される状況:



統計プロファイラーの結果は、どちらの場合も同じです。



それにもかかわらず、統計プロファイラーは、プログラムの「最も重い」場所と「最も暑い」場所の検索に完全に対応し、分析されたプログラムへの最小限の影響(および結果として、生産での使用の適合性)はすべての欠点を解消します。 さらに、Pythonを使用すると、コードをサンプリングおよび分析するときにコードの完全なスタックトレースを取得でき、より完全で詳細な画像を取得できます。



統計プロファイラーの長所と短所:

+本番稼働可能(分析されたプログラムへの影響は最小限です)

-コードに関するすべての情報からはほど遠い(実際、「ホットスポット」のみ)

-おそらく結果の誤った解釈

-適切な統計を収集するには長い時間がかかります

-いくつかの分析ツール



イベントプロファイラー



イベントプロファイラーは、すべての関数呼び出し、戻り値、例外を追跡し、これらのイベント間の間隔を測定します。 測定された時間(対応するコードセクションと呼び出し回数に関する情報と一緒に)は、さらなる分析のために保存されます。





そのようなプロファイラーの最も重要な欠点は、彼らの仕事の原理に直接由来します:分析されたプログラムにすべてのステップで介入するため、その実行プロセスは「量子力学のように」「通常の」作業条件と非常に異なる可能性があります そのため、たとえば、場合によっては、プログラムを2回以上遅くすることができます。 もちろん、本番環境では、絶望と完全な絶望の場合にのみこれをリリースすることが可能です。



それにもかかわらず、長所は短所を上回っています。そうでなければ、そのような非常に多種多様な異なるツールはありません。 実行時間とプログラムの各行の呼び出し数を分析する機能を備えた便利なインターフェイスで結果を表示することは非常に価値があり、呼び出しグラフは使用されるアルゴリズムの欠陥を識別するのに役立ちます。



イベントプロファイラーの長所と短所:

+コードの変更は不要

+プログラムに関するすべての情報を取得します

+膨大な数のツール

-場合によっては、プロファイラーはプログラムの動作を変更します

-非常にゆっくり

-生産には実質的に不適切



次の記事では、実際に手動プロファイリングと統計プロファイラーを調べます。 連絡を取り合う=)



All Articles