Ian Huff、ソフトウェア設計エンジニア
Microsoft Corporation
日本語版最終更新日 2007 年 7 月 27 日
適用対象 :
Microsoft Visual Studio 2005 Team System
Visual Studio Team Edition for Software Developers (および Team Suite)には、強力なプロファイラ機能が含まれています。
プロファイラ機能を使用するとネイティブコード、マネージコード、あるいは ASP.NET アプリケーションのパフォーマンスの問題を検知することができます。このプロファイラには2つの測定モードがあります。具体的にはサンプリング モード (ある期間定期的にプログラムの状態を検査する。大まかな測定となるがオーバーヘッドが小さい)、およびインストルメンテーション モード (すべての関数の入り口および出口を検査する。オーバーヘッドが大きいが、詳細な計測が可能) の 2 つのモードで実行できます。プロファイラが生成するパフォーマンス セッションには、パフォーマンスの問題を診断するのに役立つさまざまなビューがあります。
この TechNote ではマネージ メモリの追跡を可能にする方法を説明すると共に、メモリの問題を特定するのに役立つ 2 つの分析ビューを紹介します。
今回は、デモンストレーション用に使用するアプリケーションとして、GotDotNet から rational numbers class をダウンロードしました。このクラスには、いくつかの大きな有理数を作成し、因数分解する関数があります。最初のステップとして、ソリューションにパフォーマンス セッションを追加します。このためには、[ツール] の [パフォーマンス ツール] から [パフォーマンス ウィザード] をクリックします。これによりウィザードが開始され、有理数クラスをプロファイリングの対象として選択し、プロファイリング モードを選択することができます (ここではモードを気にする必要はありません。後で変更できます)。ウィザードが完了すると、この有理数クラスをプロファイリングの対象としたパフォーマンス エクスプローラが表示されます。ここでのプロファイリング シナリオは、次のようなものです。まず、パフォーマンス エクスプローラの左上にある開始ボタンをクリックしてアプリケーションを開始し、パフォーマンス ボタン (IDE の中ではなく、開始されたアプリケーションの中) をクリックして上記のパフォーマンス関数を開始します。パフォーマンス関数からの結果がレポートされたら、アプリケーションを閉じます。このようなシナリオを試したい場合は、同じプロジェクトをダウンロードし、それにパフォーマンス セッションを追加することで、この TechNote での分析を行ってみることができます。
通常プロファイラを実行した場合、.NET メモリ割り当て情報は全く収集されないので、割り当てビューと有効期間ビューには何も表示されません。マネージ メモリを追跡できるようにするには、パフォーマンス セッションのプロパティ ページに進みます。プロパティの最初のページで、マネージ オブジェクトの割り当て追跡と有効期間追跡が可能です (有効期間の追跡を可能にするには、割り当て情報も収集しなければなりません)。両方を使用可能にしてパフォーマンス セッションを再実行すると、割り当てビューと有効期間ビューに情報が作成されます。最初に、下記に示す割り当てビューを検討してみましょう。

左列には、プロファイリング実行中に割り当てられた異なるオブジェクト型が表示されます。この列を展開すると (String および Int32 で行っているように)、そのオブジェクトに割り当てたさまざまな関数ごとの型データに詳細化できます。デフォルトの列には、作成されたインスタンス数、割り当てられた総バイト数、全体の実行に割り当てられた総バイト数のパーセントが表示されます。このビューは、メモリの最大部分を占めるオブジェクトの識別に役立ち、意図した数より多いオブジェクトを関数が割り当てているかどうか (マネージ コードの一般的なパフォーマンス問題) の判別に役立ちます。このデータ分析の開始手段として、総バイトのパーセント別にソートし、ほとんどのスペースを消費しているのがどのオブジェクトか判断する方法があります。また、一つの関数で多数の割り当てが生じていて、それが自作した関数であれば、削減する方法を探すことができます。あるいは .NET の組み込みの関数であった場合には、より軽い関数を用いて同じ目的を達成できるか調べることができます。
どの程度のバイト数をオブジェクトが使用しているかを認識する他に、マネージ アプリケーションでどの程度長くオブジェクトが維持されるかを知ることは役に立ちます。マネージ コード オブジェクトでは、割り当ての解放が組み込みのガベージ コレクタにより処理されます。したがってプログラマは、独自のカスタム ガベージ コレクタ (組み込みのガベージ コレクタはとても良く調整されているので、処理する必要がある非常に特別な場合を除いてお勧めしません) を作成しない限り、オブジェクトがメモリ内に確保される長さを正確に制御することはありません。オブジェクトの有効期間ビュー (下記に図示) は、この種の問題の診断に役立ちます。

割り当てビューと同様に、左列には、プロファイリング実行中に割り当てられた異なるオブジェクト型が一覧表示されます。次の列 (収集された Gen 0 インスタンス、収集された Gen 1 インスタンス、収集された Gen 2 インスタンス、収集された大型オブジェクト ヒープ インスタンスおよび終了時の生存インスタンス) には、各型のオブジェクトがどの程度長く確保されてから、収集されてガベージになるか詳しく示しています。ジェネレーション 0 のガベージ コレクションは、頻繁に発生するガベージ コレクションで、主に短時間だけ存在するオブジェクトが対象です。ジェネレーション 1 コレクションは、ジェネレーション 0 よりも発生頻度が低く、ジェネレーション 2 はすべての中で最も頻度が低くなります。ジェネレーション 2 まで多数の大型オブジェクトが確保されている場合、メモリを使用していると気づかずに多くのメモリを消費しています。メモリ パフォーマンス問題があるかをチェックする簡単な方法は、ジェネレーション 2 コレクションでソートを行い、一覧表示されている項目が、長時間維持され続ける必要があるかを確認することです。また一部のオブジェクトはプロファイリング実行終了後に割り当てが解放されます。これらのオブジェクトは「終了時の生存インスタンス」列に一覧表示されます。筆者のプログラム例では、プロファイリング実行は短時間なので、すべてのオブジェクトがジェネレーション 0 で処理されるか、または最後まで保持されます。つまり、プロファイリング実行が短時間のため、有効期間問題は実際には発生しないという意味です。しかし、プロファイリング セッションの実行時間が長い場合は、この種のデータが非常に重要になります。
割り当てビューやオブジェクトの有効期間ビューは、マネージ アプリケーションのパフォーマンス エラーを検出するために役立つツールです。自動的なガベージ コレクションはプログラマの時間の節約になりますが、背後で何が行われているかを理解していなければ、重大なパフォーマンス問題につながることがあります。Visual Studio Team System に搭載の新しいプロファイラを使用すると、すべての .NET オブジェクトで発生することを正確に検出できます。