パフォーマンスと診断ハブの使い方

先週末(12/20)は、.NET ラボにお邪魔して「パフォーマンス診断 Windows ストア アプリ」というテーマでお話をさせて頂きました。今回は、この時にお話しした内容と時間の関係で割愛したデモなども含めて記載します。お話した内容は、大きく分類すると以下の2種類になります。

  • パフォーマンスを設計段階から考慮する
  • 設計したパフォーマンスを診断する
    Visual Studio パフォーマンスと診断ハブ
    Windows パフォーマンス ツールキット

全く同じものではありませんが、de:code でパフォーマンスに関するセッションがありましたので、以下の動画も参考にして下さい。
de:code Track 1 Devices トラック
Windows アプリのデバッグ、パフォーマンス測定、テスト、Windows App Certification Kit (WACK)

パフォーマンスを設計段階から考慮する

パフォーマンスを意識してアプリを設計し、実装することがとても重要です。アプリをリリースしてから、パフォーマンス問題が発生してチューニングするのとでは、かかる工数自体が異なることから、パフォーマンスを意識して設計しなければなりません。
Design Performance

設計するときの前提知識として、CPU、メモリ、補助記憶装置、ネットワークなどにおける物理的な速度を意識して適切な組み合わせを考えることが重要であることと、一般的なレイア アーキテクチャが保守や構築しやすというメリットはあるが、パフォーマンスを重要視する局面ではパフォーマンス面で不利になることを説明しました。大切なことは、要求される事項に応じて適切にアーキテクチャを組み合わせて、パフォーマンス重視であれば意図的にアーキテクチャを無視することも必要になるということです。
たとえば、適切に設計されたコンポーネントの1つのメソッドを呼び出すと、マシン語レベルではcall命令が発行されます。call命令が発行されるということは、プログラム カウンタなどの様々な情報が呼び出された命令へと切り替わるわけです。これは、数回や100回程度であれば問題にならなくても(仮に、1msとして100msです)、数万の回数になるとしたらどうなるでしょう?(10秒の単位になりますよね)。パフォーマンスを向上させるということは、このような処理にかかる時間を削ることになりますから、設計が素晴らしいことと比例しないのがパフォーマンス向上という世界になるわけです。

このような世界がパフォーマンス向上になるわけですから、設計段階からパフォーマンス目標を明確にして、その目的達成のために様々な工夫をする必要があるわけです。たとえば、ユーザー インターフェースが関係する場合であれば「応答なし」の状態は、もっとも避けるべき状況になるわけです。この「応答なし」を避けるためには、UI スレッドと異なるスレッドで実行したり、処理状況を可視化したり、ユーザーの操作の合間に分散して処理させたりなどの様々な工夫が考えられますし、要求される状況におうじて適切に組み合わせる必要があります。このような様々な工夫をした結果、パフォーマンスを達成できているかを確認する作業が診断作業になるわけです。診断した結果から、目的が達成されているかどうかを分析し、達成できていなければボトルネックを分析し、プログラムに対処コードを組み込んで、その結果を診断するという作業を繰り返すことになります。これらの診断に使用できるツールが、Visual Studio パフォーマンスと診断ハブか Windows パフォーマンス ツールキットになるわけです。

Visual Studio パフォーマンスと診断ハブ

実際のデモで使用したコードは、「パフォーマンスと診断のページからの分析ツールの実行」を基にして、ETW のトレースを組み込んだものになります。最初に、Visual Studio を起動して、診断に使用するプロジェクトを開いておきます。そうして、[分析]-[パフォーマンスと診断]からパフォーマンスと診断ハブを起動します。
1 Performace and Diagnostics Hub

パフォーマンスと診断ハブで注意する点は、以下のようなことです。

  • ターゲット アプリケーションは、必ずリリースモードにしておくこと。
  • 使用可能なツールの中で「メモリ使用量」、「JavaScriptメモリ」、「JavaScript関数の応答性」とその他の項目は排他的になるため、組み合わせることはできません。

ここでは、CPU 使用率だけにして開始ボタンをクリックします。そうすると、目的のアプリが起動します。
2 TargetApp
アプリで診断する操作を行ってから、Visual Studio へ戻り、「コレクションの停止」をクリックします。そうすると、収集したデータに基づく CPU 使用率のグラフが表示されます。
3 Performance Hub4 Performance Hub

データが表示されれば、グラフ上で範囲を指定して、コンテキスト メニューから拡大表示(ズーム)を行います。
5 Zooming

グラフを見ると、二つの山を確認することができます。1つ目の山が、同期ロジックによるボタンクリックで、2つ目の山が非同期ロジックによるボタン クリックになっています。グラフ上をクリックすると、その選択範囲に応じた関数名が下のビューに表示されるようになります。また、関数名を開くと関数がどのような別の関数を呼び出しているかを確認することができます。
6 Function Expand

次に「詳細なレポートを作成します」をクリックして、詳細レポートを開いてみます(詳細なレポートは、、時間の関係で省略しています)。
7 Detail Report

表示されているホット パスは、CPU負荷の高いメソッドになります。つまり、詳細レポートとは、CPU負荷の高い関数などをレポートし、関数をクリックすると、その詳細を確認することができるようになっています。
8 Function Detail

ここまで見てきたように Visual Studio のパフォーマンスと診断レポートの使い方は、以下のような作業を繰り返して問題点を明確にする作業になります。

  • 拡大表示によって問題個所を探す。
  • フィルターによって特定のスレッドに絞ったりする。
    フィルター表示を使用する上での注意は、「外部コードの表示」のチェックボックスにチェックを付けないということです(デフォルト)。このチェックを付けると、Win32 API を含めた分析を行うことができますが、結果が表示されるまでに長い時間がかかります。この長い待ち時間を厭わい場合のみ、試してきてください。
  • CPU 使用率の場合は、CPUに負荷を掛けている関数を探す。

今度は、「CPU使用率」と「XAML UI の応答性」で測定した診断レポートを示します。
9 XAML UI

グラフにオレンジのユーザー マークが表示されていることが、わかることでしょう。このユーザー マークこそが、ETW を使ってメッセージを出力した箇所になります。つまり、「XAML UI の応答性」では、ETW を組み合わせることによって理論的に計測したい箇所を簡単に特定することができるようになります。この機能は、Visual Studio のパフォーマンスと診断ハブのみのものになりますので、是非、ETW の使用も検討するようにしてください。ETW に出力するコードを参考までに示します。

 // マークのみの例
var logChannel = new LoggingChannel(Guid.NewGuid().ToString());
logChannel.LogMessage(message, LoggingLevel.Information);

 

Windows パフォーマンス ツールキット

Windows パフォーマンス ツールキットは、Windows Assessment and Deployment Kit に含まれているツールになります。インストール時に Windows パフォーマンス ツールキットを選択することでインストールを行うことができます。
10 ADK

インストールが完了すると、「c:\Program Files (x86)\Windows Kits\8.1\Windows Performance Toolkit」にインストールされます。このフォルダーを確認すると、「Redistributables]フォルダーがあり、x86/x64/arm 用の Windows パフォーマンス ツールキットの msi パッケージが格納されています。つまり、この msi を目的のコンピューターにインストールすることで、パフォーマンスの測定を行うことができるようになるのです。

使い方としては、スタートメニューから[Windows Kits]-[Windows Performace Recorder] を起動します。
11 WPR

「Select additional profiles for performance recording」で必ずプロファイルを選択します。ここでは、「XAML application analysis」と「First level triage」を選択しています。また、「Logging mode」をデフォルトの「Memory」にしておきます。メモリにしておく理由は、可能な限りパフォーマンスに影響をさせないためです。そして、選択したプロファイルに応じてデータ収集が行われますので、HTML/JavaScript アプリであれば「HTML application analysis」を選択するようにして、「Start」ボタンを押します。スタートしたなら、目的のアプリを起動してパフォーマンスを収集する操作を行ってから、アプリを終了します。
13 Save

「Save」ボタンをクリックすると、保存のウィンドウが表示されるのでコメントを入力後に「Save」ボタンをクリックします。
14 Save Complete

保存が完了すると、「Open in WPA」ボタンをクリックして Windows Performance Analyzer を起動します。
15 WPA

最初に行うのは、[Tarce]-[Configure Synbol Path] を使ったシンボルの設定になります。
16 Configure SymbolPath

シンボル パスには、目的のアプリの PDBのパスを忘れずに追加してください。また、既にシンボルがダウンロード済みの場合は、先頭に「.」を追加してください。ピリオドを追加することで、シンボルキャッシュが優先されるようになるので、シンボルのダウンロード時間を短縮することができます。

シンボル パスの設定が終了したら、[Trace]-[Load Synbols]をクリックして、シンボルをロードします。シンボルのロードが完了したら、[Profiles]-[Apply] をクリックして、プロファイルを適用します。
17 Apply Profiles

ここでは「Browse Catalog」ボタンをクリックして、「XamlApplicationAnalysis.wpaProfiles」を選択します(自動的にプロファイルが適用されます。自分で作成したプロファイルの場合は「Apply」ボタンをクリックしてください)。この理由は、Windows Performance Recorderで Xaml application analysis プロファイルを選択しているからです。このデモは、.NET ラボでは時間の関係で、プロファイルを使わずに独自に分析ペインを展開して説明をしていました。
18 WPA

WPA の画面は、次のような構成になっています。

  • グラフ エクスプローラー:左側に表示されており、System Activity、Computaion、Storage、Memory、Video、Powerなどがあります。このカテゴリ単位にダブル クリックや、グラフを右側にドラッグ & ドロップすることで詳細分析を行うことができます。
  • 分析ペイン:右側にタブ毎に分析ペインが表示されています。Xaml Application analysisの場合は、Big Picture、Frame Analysis、Thread Delay Analysis、Trace Markers があります。もちろん、自分で新しいタブを作成することもできます。

「Big Picture」タブの「Window Foucus」グラフで目的のプロセスである「CpuUseDemo.exe」をクリックして、コンテキスト メニューから「Filter to Selection」をクリックして、対象プロセスに絞込みを行います。次に「CPU Usage(Sampled」の表の列タイトルでコンテキスト メニューを表示して、「Function」をクリックします。
19 WPA Filter
今度は、「Window Foucus」グラフと同じように「CPU Usage(Sampled」で目的のプロセスである「CpuUseDemo.exe」をクリックして、コンテキスト メニューから「Filter to Selection」をクリックして、対象プロセスに絞込みを行います。そして、グラフの範囲を絞り込んで拡大表示(ズーム)をして問題箇所を発見するまで繰り返しながら、調べていきます。
20 Table function

拡大表示と詳細情報を使いながら調べて行くのは、Visual Studio のパフォーマンスと診断ハブと同じになります。異なるのは、Visual Studio では目的のプロジェクトで診断していたのですが、Windows パフォーマンス アナライザーでは全てのプロセスが記録されているので目的のプロセスに対してフィルターを行うと点になります。

Windows パフォーマンス ツール キットの場合は、独自のプロファイルを用意すれば、その目的に応じたデータ収集と分析が行えるようになっています。プロファイルの作成に関する情報は、ドキュメント(英語)をお読み下さい。もちろん、既存のプロファイルを使ってカスタマイズした結果もプロファイルとしてエクスポートすることができるようになっていますから、使い方に慣れるまでのハードルが高いかもしれませんが、慣れてしまえばプロファイルとして保存することで色々な場面で応用することができるようになることでしょう。

パフォーマンスと何か

パフォーマンスとは、アプリの設計時点から計画して、実装結果に対して診断してパフォーマンスを確保するものになります。リリース後にパフォーマンス問題が発生してから、調べるのは、とても工数がかかります。それは、開発者は別の作業に移っているかもしれませんし、リリースしたアプリを良く知らない者が分析するかもしれないからです。ですから、設計時点からパフォーマンスを意識して実装し、リリース前に確認しておく方がトータルなコストとしても安上がりになります。是非、Visual Studio のパフォーマンスと診断ハブなどの便利なツールを利用するようにしましょう。