たとえば、シングルスレッドプログラムに必要な時間の10倍の時間がかかる場合、その上でプロファイラーを実行できます。 「一時停止」ボタンで停止することもでき、それが何をしているのかを正確に見ることができます。
本来の速度より10%遅くても、何度も停止すると、やがて不要な処理が繰り返し実行されるようになります。通常、問題は、スタックの途中のどこかで実際には必要のない関数呼び出しです。これは問題を測定するものではありませんが、確かにそれを見つけます。
編集:反対意見は、主に1つのサンプルしか取らないと想定しています。真剣に考えている場合は、10を取ってください。平均して、40%のような、ある割合の浪費を引き起こすコード行は、そのサンプルの割合でスタックに表示されます。ボトルネック(シングルスレッドコード内)は、そこから隠すことはできません。
編集:私が何を意味するかを示すために、多くの異論は「十分なサンプルがないため、見たものが完全に偽物である可能性があります」という形式です-偶然についての漠然とした考え。ただし、ルーチン内またはルーチンがアクティブであるだけでなく、認識可能な説明のいずれかが30%の時間有効である場合、任意のサンプルで見られる確率は30%です。
次に、10個のサンプルのみを取得するとします。 10個のサンプルで問題が見られる回数は 二項分布 に従い、0回見られる確率は.028です。 1回見られる確率は.121です。確率は2倍の場合は.233、3倍の場合は.267であり、その後減少します。 2回未満見られる確率は.028 + .121 = .139なので、2回以上見られる確率は1-.139 = .861です。一般的なルールは、2つ以上のサンプルで修正できるものがあれば、修正する価値があります。
この場合、10個のサンプルで表示される可能性は86%です。 14%以内に表示されない場合は、表示されるまでサンプルを増やしてください。 (サンプル数が20に増えると、2回以上見られる可能性が99%を超えます。)したがって、正確に測定されていませんが、正確に検出されているため、理解することが重要です。プログラムカウンターではなく、データの状態に関連するものなど、プロファイラーが実際には見つけられないものである可能性があります。
Javaサーバーでは、2〜3のクイックを実行することは常にきちんとしたトリックでした Ctrl-Breakssを続けて、実行中のすべてのスレッドの2〜3個のスレッドダンプを取得します。すべてのスレッドが「存在する」場所を単に見れば、パフォーマンスの問題がどこにあるかを非常にすばやく特定できる場合があります。
このテクニックは、私が知っているどのテクニックよりも2分間でより多くのパフォーマンスの問題を明らかにすることができます。
それは時々それが機能し、時にはそれがあなたに完全に間違った答えを与えるからです。プロファイラーは、正しい答えを見つけるはるかに優れた記録を持っており、通常、より早く到達します。
これを手動で行うことは、実際には「迅速」または「効果的」とは言えませんが、これを自動的に行うプロファイリングツールがいくつかあります。 統計プロファイリング とも呼ばれます。
コールスタックサンプリングは、特に任意の場所で時間を費やしている可能性がある大規模で複雑なコードベースを調べる場合に、プロファイリングに非常に役立つテクニックです。これには、インタラクティビティにとって重要な実時間でCPUの使用状況を測定するという利点があり、各サンプルでコールスタックを取得すると、whyを確認できます関数が呼び出されています。私はそれを頻繁に使用しますが、 Luke Stackwalker や OProfile などの自動化ツールや、ハードウェアベンダーが提供するさまざまなものを使用しています。
私が行う作業では、手動サンプリングよりも自動化ツールを好む理由は statistical power です。 1つの関数が実行時間の40%を占める場合、10個のサンプルを手動で取得することは問題ありません。平均して4つのサンプルがあり、常に少なくとも1つだからです。しかし、何百ものリーフ関数があり、実行時間の1.5%を超えないフラットプロファイルがある場合は、より多くのサンプルが必要です。
さまざまな種類の魚がいる湖があるとします。湖の魚の40%がサケ(そして60%が「その他すべて」)である場合、湖にたくさんのサケがいることを知るために10匹の魚を捕まえるだけで済みます。しかし、何百もの異なる種類の魚がいて、それぞれの種類が個別に1%未満の場合、「この湖は0.8%のサケと0.6%のマスです」と言えるようにするには、10匹を超える魚を釣る必要があります。 」
同様に、私が取り組んでいるゲームでは、数百の異なるエンティティで数十の関数を呼び出すいくつかの主要なシステムがあり、これらはすべて1秒あたり60回発生します。これらの関数の一部の時間は、一般的な演算(malloc
など)に集中していますが、ほとんどの場合、そうではなく、いずれの場合も、フレームあたり1000 µsを超える単一の葉はありません。
trunk関数を見て、「衝突に10%の時間を費やしている」ことを確認できますが、それほど役に立ちません。衝突の正確なwhereを知るために、どの関数をスクイーズするかを知っています。 「衝突を少なくする」だけでは、特に機能を破棄することを意味する場合に限り、これまでのところはうまくいきません。 「魔法のミサイルは非常に速く移動して多くのセルに触れるため、「 オクツリー 」という狭いフェーズでキャッシュミスに平均600μs/フレームを費やしています」正確な修正を追跡することができます:より良い木か遅いミサイルのどちらか。
たとえばstricmp
に大きな20%のかたまりがあった場合、手動でのサンプリングは問題ありませんが、私たちのプロファイルではそうではありません。代わりに、たとえば、フレームの0.6%からフレームの0.4%に取得する必要がある数百の関数があります。 1秒あたり300回呼び出される50μsの機能ごとに10μsを削る必要があります。このような精度を得るには、さらにサンプルが必要です。
しかし、本質的には、Luke Stackwalkerが行うことはあなたが説明することです。ミリ秒ごとに、プログラムを停止し、コールスタックを記録します(正確な命令と [〜#〜] ip [〜#〜]の行番号を含む) )。一部のプログラムでは、プロファイルを有効に作成するために数万のサンプルが必要なだけです。
(もちろん、これについては以前に話しましたが、これは議論を要約するのに適した場所だと思いました。)
両側の宗教的なトーンに驚きました。
プロファイリングは素晴らしく、できる場合は確かにより洗練されていて正確です。できない場合もありますが、信頼できるバックアップを用意しておくのは良いことです。一時停止のテクニックは、電動工具が遠すぎる場合や、バッテリーが消耗した場合に使用する手動ドライバーのようなものです。
ここに短い実話があります。アプリケーション(バッチ処理タスクの一種)が6か月間運用環境で問題なく実行されていましたが、 "遅すぎる"ため、オペレーターが突然開発者に電話をかけています。彼らは、本番環境でサンプリングプロファイラーをアタッチすることはできません!すでにインストールされているツールを使用する必要があります。 Process Explorer を使用するだけで生産プロセスを停止することなく(この演算子は既にマシンにインストールされています)、スレッドのスタックのスナップショットを見ることができます。スタックの一番上をちらりと見て、Enterキーでそれを消し、別のマウスクリックで別のスナップショットを取得できます。毎秒ほど簡単にサンプルを取得できます。
スタックの最上部がデータベースクライアントライブラリDLL(データベースで待機中))にあるか、別のシステムDLL(システム操作を待機中)、または実際にはアプリケーション自体のいくつかのメソッド。この場合、私が正しく覚えていれば、10回のうち8回はアプリケーションがシステムにあることにすぐに気づきましたDLLファイル呼び出しによるネットワークファイルの読み取りまたは書き込み。確かに最近の「アップグレード」により、ファイル共有のパフォーマンス特性が変更されました。アプリケーションが何をしているかを確認するための迅速でダーティな(システム管理者の許可を得た)アプローチがなければ本番環境では、問題を修正するよりも、問題を測定するためにはるかに多くの時間を費やしたでしょう。
一方、パフォーマンス要件が「十分」を超えて実際に限界を超えると、プロファイラーが不可欠になり、緊密に結びついた上位10または20のすべてのホットスポットからサイクルを剃ることができるようになります。プロジェクトの期間中、適度なパフォーマンス要件を維持しようとしている場合でも、適切なツールを揃えて測定とテストを行い、それらを自動テストプロセスに統合すれば、非常に役立ちます。
しかし、(いわば)電源が切れていてバッテリーが切れているときは、手動ドライバーの使い方を知っているのは素晴らしいことです。
したがって、直接的な答えは、プログラムを停止することから何を学ぶことができるかを知ることですが、精密ツールも恐れないでください。最も重要なことは、どのジョブがどのツールを必要とするかを知ることです。
プログラマーが実際に行うことと、他の人が行うことを推奨することには違いがあります。
私は実際にこの方法を使用する多くのプログラマー(私も含む)を知っています。それは本当に最も明白なパフォーマンスの問題を見つけるのに本当に役立ちますが、それは速くて汚いです、そしてそれは機能します。
しかし、すべての警告を説明するには時間がかかりすぎるので、他のプログラマにそれを実行するようには言いません。この方法に基づいて不正確な結論を下すことは非常に簡単であり、まったく機能しない領域がたくさんあります。 (たとえば、そのメソッドは、ユーザー入力によってトリガーされるコードを明らかにしません)。
したがって、法廷で嘘発見器や「goto」ステートメントを使用するのと同じように、すべてに用途があるとしても、使用をお勧めしません。
「なぜそれはもっとよく知られていないのですか?」その答えは主観的なものになります。おそらくそれがよく知られていない理由は、プロファイリングが現在の問題の解決策ではなく長期的な解決策を提供するためです。マルチスレッドアプリケーションには効果がなく、レンダリングにかなりの時間を費やしているゲームなどのアプリケーションには効果がありません。
さらに、シングルスレッドアプリケーションで、最も多くの実行時間を消費することが予想されるメソッドがあり、他のすべてのメソッドの実行時間を短縮したい場合は、どのセカンダリメソッドを重点的に使用するかを決定するのが難しくなります。最初に。
プロファイリングのプロセスは、機能し、機能する許容可能な方法ですが、プロファイリングはより多くの情報を提供し、より詳細なパフォーマンスの向上と回帰を示すという利点があります。
十分にインスツルメントされたコードがある場合は、特定のメソッドがどれだけ長く続いているかだけではありません。すべてのメソッドを見ることができます。
プロファイリングあり:
次に、各変更後にシナリオを再実行して、パフォーマンスの改善/回帰の程度を判断できます。
さまざまなハードウェア構成でコードをプロファイルして、実稼働ハードウェアで十分かどうかを判断できます。
負荷およびストレステストのシナリオでコードをプロファイルして、情報量がパフォーマンスに与える影響を特定できます。
ジュニア開発者は、ビーチやパブ、あるいはその両方にいる間に6か月でコードのプロファイルを再作成できるため、コードへの変更の影響を視覚化しやすくなります。ビーチパブ、twt。
エンタープライズコードは常にある程度のプロファイリングを持つ必要があるため、プロファイリングはより重要視されます。コードの重要性が高ければ高いほど、プロファイリングとテストが多くなります。
あなたのアプローチは有効であり、別の項目は開発者のツールボックスです。プロファイリングの方が重要です。
サンプリングプロファイラーが役立つのは、
「デバッグ」モードでのプログラムの実行中に一時停止ボタンを押すと、パフォーマンスの最適化を実行するための適切なデータが提供されない場合があります。端的に言えば、プロファイリングの大まかな形です。
プロファイラーの使用を避ける必要がある場合は、ロガーを使用してから、スローダウン係数を適用して、実際の問題がどこにあるかを「推測」することをお勧めします。ただし、プロファイラーは推測を行うための優れたツールです。
デバッグモードで一時停止ボタンを押しても、アプリケーションの動作の実際の画像が表示されない理由は、デバッガーがアプリケーションの特定の部分を遅くする可能性のある追加の実行可能コードを導入するためです。デバッグ環境でのアプリケーションのスローダウンの考えられる理由については、 Mike Stallのブログ投稿 を参照できます。ポストは、ブレークポイントが多すぎる、例外オブジェクトの作成、最適化されていないコードなどの特定の理由に光を当てます。最適化されていないコードに関する部分は重要です-「デバッグ」モードでは、多くの最適化が行われます(通常、コードのインライン化と再順序付け)ウィンドウからスローされ、デバッグホスト(コードを実行するプロセス)とIDE=コード実行を同期する)を有効にします。したがって、「デバッグ」モードで一時停止を繰り返し押すと、悪い考え。
これらは、メソッドで有用な結果を得るために作業している簡単な例でなければなりません。あなたの「迅速かつ効果的な」方法でまともな結果が得られるであろうプロファイリングが(どのような方法で)有用であったプロジェクトは考えられません。一部のアプリケーションを開始および停止するのにかかる時間は、すでに「クイック」のアサーションを問題にしています。
繰り返しになりますが、自明ではないプログラムでは、あなたが主張する方法は役に立ちません。
編集:「なぜそれはよりよく知られていないのですか」について?
私の経験では、コードレビューは低品質のコードとアルゴリズムを回避し、プロファイリングはこれらも同様に見つけます。あなたが素晴らしい方法を続けたいのであれば-しかし、私はほとんどの専門家コミュニティにとって、これは試すべきことのリストのはるか下にあると思います。
小さなサンプルセットではかなり不正確で、大きなサンプルセットを取得するには多くの時間がかかり、他の有用なアクティビティに費やした方がよいでしょう。
スタックトレーススナップショットでは、アプリケーションのストロボスコープのX線のみを表示できます。プロファイラーがあなたに与えるかもしれないより多くの蓄積された知識を必要とするかもしれません。
秘訣は、ツールをよく理解し、目前の仕事に最適なものを選択することです。
プログラムがproductionであり、支払いを行うクライアントまたは同僚によって同時に使用されている場合はどうなりますか?プロファイラーを使用すると、干渉することなく観察できます(もちろん、 Heisenbergの原理 のように少しヒットするためです)。
プロファイリングにより、はるかに豊富で詳細な正確なレポートも得られます。これは長期的にはより速くなります。
コードをステップ実行すると、詳細な情報やトラブルシューティングアルゴリズムを確認できます。それは、樹木を実際に間近で見、樹皮と枝の静脈を個別にたどるようなものです。
プロファイリングを使用すると、全体像を確認し、問題点をすばやく特定できます。たとえば、後ろに一歩進んだり、森全体を調べたり、最も高い木に気づいたりできます。関数呼び出しを実行時間の長さで並べ替えることにより、問題のある領域をすばやく特定できます。
私はこの方法を Commodore 64 BASIC に何年も前に使用しました。それがどれほどうまく機能するかは驚くべきことです。
編集2008/11/25:わかりました、Vineetの返答により、ようやくここで問題が何であるかがわかりました。遅くならないよりはましだ。
どういうわけか、パフォーマンスの問題はパフォーマンスを測定することによって見つかるという考えは、土地でゆるくなりました。それは目的を混乱させる手段です。どういうわけか私はずっと前にプログラム全体をシングルステップすることでこれを避けました。私はそれを人間の速度に落としたために自分を非難しませんでした。私はそれが間違っているか不必要なことをしていないかどうかを確かめようとしていました。これがソフトウェアを高速化する方法です。不要な操作を見つけて削除します。
最近のシングルステップに耐えられる人はいませんが、次善の策は、ランダムに多数のサイクルを選び、その理由を尋ねることです。 (これは、コールスタックがよく伝えることができることです。)それらのかなりの割合に正当な理由がない場合は、それについて何かを行うことができます。
最近では、スレッディングと非同期の場合はさらに難しくなっていますが、それが[〜#〜] i [〜#〜]ソフトウェアを調整する方法です-不要なサイクルを見つけることによって。それがどれほど速いかを見るのではなく、私は最後にそれを行います。
コールスタックのサンプリングが間違った答えを出さない理由と、多くのサンプルが必要とされない理由は次のとおりです。
関心のある期間中、プログラムが必要以上の時間を費やしている場合、サンプリングしていない場合でも、コールスタックは継続的に存在します。
命令がNのうちM = 2以上のサンプルで表示される場合、そのP(I)はおよそM/Nであり、明らかに重要です。
命令が表示されない場合の唯一の方法は、命令がコールスタックにない場合に、すべてのサンプルを魔法のように時間を計ることです。それがほんの少しの時間存在するという単純な事実が、それをプローブに公開するものです。
したがって、パフォーマンスチューニングのプロセスは、コールスタックの複数のサンプルをオンにすることによって頭を上げる命令(主に関数呼び出し命令)を選択するという単純な問題です。 これらは森の中の高い木です。
呼び出しグラフ、関数の所要時間、関数の呼び出し回数、または再帰について気にする必要がないことに注意してください。
プロファイラーではなく、難読化に反対しています。それらは多くの統計を提供しますが、ほとんどはP(I)を提供せず、ほとんどのユーザーはそれが重要であることを認識していません。
フォレストやツリーについて話すことはできますが、コードを変更することで修正できるパフォーマンスの問題については、命令、特にP(I)が高い命令を変更する必要があります。したがって、できればシャーロックホームズをプレイせずに、それらがどこにあるかを知る必要があります。スタックサンプリングは、それらがどこにあるかを正確に伝えます。
この手法は、マルチスレッド、イベント駆動型、または本番環境のシステムでは採用が困難です。プロファイラーがP(I)を報告する場合、それは本当に役立ちます。
プログラムが大きくなるほど、プロファイラーはより便利になります。数千の条件付きブランチを含むプログラムを最適化する必要がある場合は、プロファイラーが不可欠です。テストデータの最大のサンプルを入力し、完了したら、プロファイリングデータをExcelにインポートします。次に、可能性のあるホットスポットに関する想定を実際のデータと照合します。いつも驚きがあります。
私は通常、タイムスライスを超過しているリアルタイムプログラムで使用しました。毎秒60回実行する必要があるコードを手動で停止して再起動することはできません。
また、私が作成したコンパイラーのボトルネックを追跡するためにも使用しました。手動でこのようなプログラムを壊そうとは思わないでしょう。なぜなら、ボトルネックがある場所で壊れているのか、それともOSが許可されたときにボトルネックの後の場所で壊れているのかを知る方法がないからです。やめてまた、主要なボトルネックが何もできないものであるにもかかわらず、システム内の他の大きなボトルネックをすべて解消したい場合はどうでしょうか。 allがどこにあるかに関する適切なデータがない場合に、最初に攻撃するボトルネックに優先順位を付ける方法と、それぞれの相対的な影響は何ですか?