次の方法で共有


Windows イベント トレーシング

Windows 7 のコア インストルメンテーション イベント、第 2 部

Insung Park 博士および Alex Bendetov

2 部構成のシリーズ「Windows 7 のコア インストルメンテーション イベント」の第 2 部へようこそ。初回は、Windows イベント トレーシング (ETW) テクノロジとコア OS インストルメンテーションについての概要を説明しました。また、OS イベントを取得し、利用するためのツール サポートについても触れました。今回の第 2 部では、コア OS の各種サブコンポーネントからのイベントについて詳しく説明します。また、さまざまなシステム イベントを組み合わせて、システムの動作を総合的に把握する方法についても説明します。これについては、一連の Windows PowerShell スクリプトを使用して例を示します。

ディスク、ファイル、ファイルの詳細、およびドライバーのイベント

プログラムの観点では、ファイルを開く、読み取る、または書き込むといった操作は、ディスクの内容にアクセスする方法です。しかし、キャッシュやプリフェッチなどの最適化のおかげで、すべてのファイル IO 要求によって、直ちにディスク アクセスが発生するわけではなくなりました。さらに、ファイルの内容が複数のディスクに分散されていたり、特定のディスク デバイスがミラーリングやストライピングをサポートしていたりと、状況はさまざまです。このような状況では、ファイルから 1 ブロックのデータを読み取るだけで、1 つ以上のディスクに複数回のアクセスが発生します。ファイルやディスクにアクセスする際に発生するイベントには、ファイル IO の開始、ファイル IO の完了、ディスク アクセスの開始、ディスク アクセスの終了、分割 IO、ドライバー アクティビティ、およびファイル (の名前と一意のキーの) マップがあります。

ユーザー アプリケーションからのファイル アクセス要求と、ユーザー アプリケーションに返される要求の完了通知は、複数のコンポーネントからなるスタックを経由します。Windows IO システムでは、IO 操作は IO 要求パケット (IRP) と呼ばれるエンティティによって追跡されます。ユーザーが開始した IO 操作は、IO マネージャーに渡されるときに、IRP に変換されます。IRP が一連のコンポーネントを通過するときに、各コンポーネントは要求の処理に必要な作業を実行し、IRP を更新して、必要に応じて、次に要求を処理するコンポーネントに渡します。IO 要求のすべての要件が満たされると (簡単な場合では、要求されたファイルのブロックをディスクから取得するなど)、登録されている完了ルーチンが呼び出されて、追加のデータ処理を実行し、要求されたデータをユーザー アプリケーションに返します。

コア IO システムの上位層では、ファイル IO イベントがアプリケーションによって発行された操作を記録します。ファイル IO イベントの種類には、作成、読み取り、書き込み、フラッシュ、名前の変更、削除、クリーンアップ、終了、情報の設定、情報の照会、ディレクトリの列挙、およびディレクトリ変更通知があります。作成、読み取り、書き込み、フラッシュ、名前の変更、削除などの操作はその名のとおりの内容で、必要に応じてファイル キー、IO 要求パケット (IRP) ポインター、ブロック サイズ、ファイルのオフセットなどのデータ項目を含みます。情報の設定イベントと情報の照会イベントは、ファイル属性が設定または照会されたことを示します。クリーンアップ イベントは、ファイルへの最後のハンドルが閉じられたときに記録されます。終了イベントは、ファイル オブジェクトが解放される直前を示します。ディレクトリの列挙イベントとディレクトリ変更通知イベントは、それぞれ、ディレクトリが列挙された時点または登録されているリスナーにディレクトリ変更通知が送信された時点で記録されます。ファイル IO イベントは、ファイル IO 操作が要求された時点で ETW に記録されます。ファイル IO 操作の完了と操作にかかった時間を確認する場合は、ファイル IO 完了イベントを有効にします。これは、IRP ポインターを使って元のファイル IO イベントに関連付けることができます。ファイル IO 完了イベントでは、IRP ポインターとリターン ステータスが記録されます。

ディスク イベントは IO スタックの下位層で記録されます。このようなイベントには、ディスク アクセス固有の情報が含まれます。読み取り操作や書き込み操作によって、ディスクの読み取りイベントや書き込みイベントが生成されます。これらのイベントには、ディスク番号、転送サイズ、アクセス対象アドレスのバイト オフセット、IRP ポインター、およびアクセスの応答時間といった情報が含まれます。フラッシュ イベントは、ディスクのフラッシュ操作を記録します。ファイル IO イベントは操作の開始時に記録されますが、ディスク IO イベントは IO 完了時に記録されます。ユーザーは、すべてのディスク IO イベントに対して、追加でディスク IO 初期化イベント (ReadInit、WriteInit、および FlushInit イベント) を収集することもできます。前述のとおり、たとえば、要求した内容が既にキャッシュ内にある場合や、ディスクへの書き込み操作がバッファリングされる場合があるため、すべてのファイル IO イベントに対応するディスク IO イベントがあるわけではありません。分割 IO イベントは、基盤のミラーリング ディスク ハードウェアによって、IO 要求が複数のディスク IO 要求に分割されたことを示します。このようなハードウェアを使用していなければ、分割 IO イベントを有効にしても、分割 IO イベントは記録されません。分割 IO イベントでは、元の親 IRP が複数の子 IRP にマップされます。

ディスク IO、ファイル IO、および分割 IO イベントには、開かれているファイルに対して作成される一意のファイル キーが含まれます。このファイル キーを使用して、IO システム内の関連 IO 操作を追跡できます。ただし、そのファイル操作の対象になる実際のファイルの名前は、ファイル IO イベントにもディスク IO イベントにも記録されません。ファイルの名前を解決するには、ファイルの詳細イベントが必要です。開いているファイルはすべて列挙され、それぞれのファイル キーとファイル名が記録されます。ステート マシンのシミュレーションを行っている場合、ファイル オブジェクトはファイル キーを基に追跡されて、ファイル IO 要求と実際のディスク アクセスが記録されます。その後、ファイルの詳細イベントが発生すると、オブジェクト内で名前が更新されます。歴史的な理由から、ディスク IO イベントとファイルの詳細イベントのファイル キーは、FileObject と名付けられています。ほとんどのファイル IO イベントには、ファイル オブジェクトとファイル キーが含まれます。

ドライバー イベントは、ドライバーでのアクティビティを示し、デバイスの種類によっては、ディスク IO アクティビティと重複することがあります。ドライバー イベントは、Windows Driver Model (WDM) に詳しいユーザーが興味を持つかもしれません。ドライバー インストルメンテーションは、ドライバー IO 関数呼び出しと完了ルーチン関連のイベントを追加します。ドライバー イベントには、各イベントの種類に応じて、ファイル キー、IRP ポインター、ルーチン アドレス (メジャー関数とマイナー関数および完了ルーチン) などのドライバー データを含みます。

IO イベントは、通常、大量のイベントになるため、カーネル セッションのバッファーの数やサイズを増やす (logman の -nb オプション) 必要が生じる可能性があります。また、IO イベントは、ファイルの使用状態、ディスク アクセス パターン、およびドライバー アクティビティの分析に便利です。ただし、ディスク IO イベントを除いて、IO イベントのプロセスおよびスレッド ID 値は、有効ではありません。イベントを発生させたスレッド、ひいてはプロセスに、これらのアクティビティを正しく関連付けるには、コンテキスト スイッチ イベントの追跡を検討してください。

ネットワーク イベント

ネットワーク イベントは、ネットワーク アクティビティが発生したときに記録されます。カーネル セッションからのネットワーク イベントは、TCP/IP 層と UDP/IP 層で発生します。TCP/IP イベントは、送信、受信、切断、再転送、再接続、コピー、失敗の操作が発生したときに、記録されます。これらのどのイベントにも、パケット サイズ、および送信元と送信先の IP アドレスとポートが含まれますが、失敗イベントのみはこのような情報がないため例外です。また、これらのネットワーク操作は送信/受信プロセス コンテキストで実行されないことが多いため、送信イベントの送信元プロセス ID と受信イベントの送信先プロセス ID も含まれます。つまり、ネットワーク イベントは、スレッドではなく、プロセスにより発生元を特定できます。UDP/IP イベントは、送信イベントか受信イベントのどちらかであり、上記のデータ項目を含みます。また、操作の種類 (送信、受信など) ごとに、IPv4 プロトコルのイベントと IPv6 プロトコルのイベントの 1 組のイベントがあります。IPv6 プロトコルのイベントは、Windows Vista で追加されました。

レジストリ イベント

ほとんどのレジストリ操作は ETW に対応していて、イベント ヘッダーのプロセス ID やスレッド ID により、発生元のプロセスやスレッドを特定できます。レジストリ イベントのペイロードには、完全なレジストリ キー名は含まれません。代わりに、開かれているレジストリ キーごとに、キー制御ブロック (KCB: Key Control Block) という一意キーが含まれます。カーネル セッションの最後に、これらのキーと完全なレジストリ名をマップする停止イベントが記録されます。レジストリ名を解決するには、ファイル名の解決に使用したのと同様の手法を使用する必要があり、これらのマップ イベントを使用して、ステート マシン内のレジストリ オブジェクトを更新します。レジストリ イベントは、最適化を行うためのアクセス パターンの分析や冗長アクセスの特定に利用されてきました。レジストリ イベントのペイロードには、操作のリターン ステータスが含まれます。これは、レジストリ操作の失敗の監視や、発生する可能性のあるアプリケーションの問題のトラブルシューティングに使用できます。

図 1 プロセス テーブルを出力するための Get-ETW-PID-List スクリプト

<####################
 # Get-ETW-PID-List
 # \@brief Takes in an XML stream and prints the list of process names
 # with PIDs that were detected in the incoming stream.
 ####################>
function Get-ETW-PID-List([Switch] $print) {
    begin {
        $pidlist = new-object System.Collections.Hashtable
        $procid = 0
        $procname = ""
    }

    process {
        $xmldata = $_
        
        # For each Process event, grab process id and binary name 
        # and add to the list. 
        foreach ($e in $xmldata.Events.Event) {
            if ($e.RenderingInfo.EventName.InnerText -eq "Process") {
                foreach ($d in $e.EventData.Data) {
                    # Grab process id.
                    if ($d.Name -eq "ProcessId") {
                       $procid = $d.InnerText
                    # Grab the process name.
                    } elseif ($d.Name -eq "ImageFileName") {
                        $procname = $d.InnerText
                    }
                }
                if (!$pidlist.Contains($procid)) {
                    $pidlist.add($procid, $procname) | Out-Null
                }
            }
        }
    }

    end {
        remove-variable xmldata

        if ($print) {
            "{0,-29}| PID" -f "Binary Name"
            "-------------------------------------"
            foreach ($item in $pidlist.Keys) {
                "{0,-30}({1})" -f $pidlist.$item,$item
            }
        } else {
            return $pidlist
        }
    }
}

図 2 Get-ETW-PID-List スクリプトの結果

PS C:\tests> $xmldata | Get-ETW-PID-List -print
Binary Name                  | PID
-------------------------------------
dwm.exe                       (2776)
powershell.exe                (2384)
svchost.exe                   (708)
notepad.exe                   (4052)
iexplore.exe                  (4284)
...
iexplore.exe                  (4072)
svchost.exe                   (3832)
smss.exe                      (244)
System                        (4)
spoolsv.exe                   (1436)
Idle                          (0)

サンプルを基にしたプロファイル イベント

サンプルを基にしたプロファイル イベント (以下、プロファイル イベント) では、CPU が時間を費やした対象を追跡できます。プロファイル イベントは、CPU 使用率を高い精度で計算するために使用できます。プロファイル イベントが有効になると、Windows カーネルはプロファイル割り込みを有効にします。これにより、プロファイル イベントが決められたペースでプロセッサごとに記録されます (既定値は、プロセッサごとに 1 秒につき 1000 回)。一部のコンピューターでは低電力モードの間は、プロファイル イベントが一時的に無効にされる場合があることに注意してください。プロファイル イベントのペイロードは、現在プロセッサで実行されているスレッドのスレッド ID と、プロファイル割り込み時に登録された命令ポインターの値で構成されます。Windows 7 では、プロファイル イベントのペイロードには、実行コンテキストの識別に必要なフラグ (スレッド/DPC/ISR) も含まれます。

図 3 プロセスの詳細情報を出力するための Get-ETW-PID-Info スクリプト

<####################
 # Get-ETW-PID-Info 
 # \@brief Retrieves various information about a particular process id
 ####################>
function Get-ETW-PID-Info([Int] $p, [switch] $i, [switch] $t) {
    begin {
        $threadlist = New-Object System.Collections.ArrayList
        $imagelist = New-Object System.Collections.ArrayList
        $procname = ""
    }

    process {

        $xmldata = $_
        
        $sievedxml = $($xmldata | Get-ETW-PID-Events $p).$p

        foreach ($e in $sievedxml.Events.Event) {
            if ($e.RenderingInfo.EventName.InnerText -eq "Process") {
                foreach ($d in $e.EventData.Data) {
                    # Grab the process binary name 
                    if ($d.Name -eq "ImageFileName") {
                        $procname = $d.InnerText
                    }
                }
            }
            if ($e.RenderingInfo.EventName.InnerText -eq "Image") {
                foreach ($d in $e.EventData.Data) {
                    # Grab the loaded image name and add it to the list
                    if ($d.Name -eq "FileName") {
                        if (!$imagelist.contains($d.InnerText)) {
                            $imagelist.add($d.InnerText) | Out-Null
                        }
                    }
                }
            }
            if ($e.RenderingInfo.EventName.InnerText -eq "Thread") {
                foreach ($d in $e.EventData.Data) {
                    # Grab thread id and add it to the list
                    if ($d.Name -eq "TThreadId") {
                        $tid = $d.InnerText
                        if (!$threadlist.contains($tid)) {
                            $threadlist.add($tid) | Out-Null
                        }
                    }
                }
            }
        }
    }

    end {
        "Process Name: $procname"
        if ($t) {
            "Thread List: ($($threadlist.Count))"
            $threadlist | Sort -descending
        } else {
            "Thread Count: $($threadlist.Count)"
        }
        if ($i) {
            "Image List ($($imagelist.Count)):"
            $imagelist | Sort
        } else {
            "Images: $($imagelist.Count)"
        }
    }
}

CPU 使用率は、プロファイル イベントを使用して概算値を求めることができます。これは、スレッド ID がアイドル スレッドの ID ではないプロファイル イベントの割合で求められます。プロセスごとの CPU 使用率の分布を把握するには、さらに個々のプロセスのプロセス イベントのペイロードに記録されているスレッド ID を追跡するための作業が必要です。この 2 部構成シリーズの第 1 部で説明したように、プロセス イベントとスレッド イベントにステート マシンを利用できる場合、プロセスごとの CPU 使用率レポートを生成することは簡単です。また、イメージの読み込みイベントを利用して、CPU 使用率と読み込み済みモジュールを対応付けることもできます。命令ポインターと読み込み済みモジュールのアドレス範囲とを比較することで、バイナリ イメージ、ひいてはモジュールごとの CPU 使用率のプロファイルへの命令ポインターの場所がわかります。バイナリ シンボルがある場合は、DbgHelp ライブラリを使用して命令ポインターから関数名を取得できます。プロファイル イベントのコール スタックが有効であれば、関数がどのようにして呼び出されたかを突き止めることさえできます。これは、命令ポインターが頻繁に使用されるライブラリ関数を指している場合、非常に便利です。

スレッドの準備完了イベント

システムが実行中のスレッドを保留にする理由はいくつかあります。最も一般的な理由の 1 つは、他のスレッドが関連するタスクを完了しないと、タスクを続行できないため、待機する必要がある場合です。このような実行上の依存関係は、イベント、セマフォ、タイマーなどのオブジェクトが設定されるのを待機している間、スレッドの実行がブロックされるという形で現われます。Windows OS スケジューラ (別称、ディスパッチャー) は、別のスレッド、DPC、またはタイマーによって、ブロックが解除されたスレッドを追跡します。コンポーネントとスレッド間の依存関係は、開発中に簡単には確認も予測もされません。予期されない遅延が発生した場合、問題の根本原因を突き止めることは難しくなります。

スレッドの準備完了 (またはディスパッチャー) イベントは、このような問題の診断を支援するために追加されました。スレッドのブロックが解除され (実行準備ができ)、ディスパッチャーの準備完了キューに入れられると、スレッドの準備完了イベントが記録されます。このペイロードには、実行準備が完了したスレッドのスレッド ID が含まれます。スレッドの準備完了イベントのチェーンを辿ることで、実行の依存関係も明らかになり、実行の依存関係のチェーンを追跡できます。前述のコンテキスト スイッチ イベントは、実行準備ができたスレッドが、実際にいつ実行されるスケジュールになっているかを示します。スレッドの準備完了イベントに対して有効なコール スタックから、待機中のスレッドのブロックを解除したコード位置がわかる場合があります。スレッドの準備完了イベントは、Windows 7 から新たに提供されるイベントです。

システム コール イベント

システム コール イベントは、Windows コア OS システム コールの開始と終了を示します。システム コールは、Windows カーネルへのインターフェイスで、多数の API で構成されます。このインストルメンテーションは、ユーザー モード アプリケーションとカーネル モード コンポーネントによるシステム コールを監視するために追加されました。システム コール イベントには 2 種類あります。1 つはシステム コール開始イベントで、システム コールが呼び出されたことを示し、呼び出されたシステム サービスに対応するルーチンのアドレスを記録します。もう 1 つはシステム コール終了イベントで、システム コールが終了したことを示し、このペイロードには API 呼び出しからの戻り値が含まれます。システム コール イベントは、システム コールのアクティビティと待機時間の統計分析に便利ですが、一部の IO イベントやメモリ イベントと同様、現在のプロセスとスレッド ID をヘッダーに含まない状態で記録されます。システム コールのアクティビティをプロセスやスレッドと関係付けるには、コンテキスト スイッチ イベントを同時収集して、ステート マシンによるシミュレーション中に、システム コール イベントのイベント ヘッダーにある CPU ID を使用して、CPU 上で実行されている現在のスレッドを追跡する必要があります。これについては、この 2 部構成シリーズの第 1 部で説明しています。

Advanced Local Procedure Call のイベント

ローカル プロシージャー コール (LPC) は、長年にわたり Windows プラットフォームで効率のよいローカル プロセス間通信 (IPC) メカニズムとして使用されてきました。Windows Vista では、IPC のニーズに応え、効率的かつ安全性の高い手段として、Advanced Local Procedure Call (ALPC) が用意されました。ALPC は、ローカルのリモート プロシージャ コール (RPC) 向けトランスポート メカニズムとしても使用されています。ALPC コンポーネントは ETW に対応していて、送信、受信、新しい応答の待機、新しいメッセージの待機、および待機解除イベントを生成します。

システム構成イベント

カーネル セッションが終了するときに、ETW は、イベント収集対象のコンピューターのシステム構成についてのイベントをいくつか記録します。さまざまなパフォーマンス分析シナリオで、基盤のハードウェアとソフトウェアの構成に関する情報は、システムの動作を理解するうえで非常に役立ちます。特に、イベントの分析を行うコンピューターと、イベントが収集されたコンピューターとが異なる場合に有用です。システム構成イベントは、CPU、グラフィック カード、ネットワーク カード、PnP デバイス、IDE デバイス、物理および論理ディスク構成、サービスについての情報を提供します。システム構成イベントのペイロードは、記録対象のデバイスまたは構成によって異なりますが、通常は構成を説明する文字列と主な仕様についての情報が含まれます。

図 4 Get-ETW-PID-Info スクリプトの結果

PS C:\tests> $xml | Get-ETW-PID-Info 4052 -i
Process Name: notepad.exe
Thread Count: 2
Image List (31):
\Device\HarddiskVolume2\Windows\System32\advapi32.dll
\Device\HarddiskVolume2\Windows\System32\dwmapi.dll
\Device\HarddiskVolume2\Windows\System32\gdi32.dll
\Device\HarddiskVolume2\Windows\System32\imm32.dll
\Device\HarddiskVolume2\Windows\System32\kernel32.dll
\Device\HarddiskVolume2\Windows\System32\KernelBase.dll
...
\Device\HarddiskVolume2\Windows\System32\version.dll
\Device\HarddiskVolume2\Windows\System32\winspool.drv

図 5 VM 操作を呼び出した回数が最も多いプロセスの上位 n プロセスを出力するための Get-ETW-Top-VMops スクリプト

<####################
 # Get-ETW-Top-VMops
 # \@brief Gets the top $num processes ranked by the number of virtual 
   memory events
 ####################>
function Get-ETW-Top-VMops ([Int] $num) {
    begin {
        $hold = @{}
    }

    process {

        $xmldata = $_

        # Get a list of the PIDs
        $list = $xmldata | Get-ETW-PID-List
       
        # Iterate through each PID
        $eventxml = $xmldata | Get-ETW-PID-Events $list.Keys

        foreach ($pd in $list.Keys) {

            $vmops = 0

            # Count the number of VM events
            foreach ($e in $eventxml.$pd.Events.Event) {
                [String] $type = $e.RenderingInfo.EventName.InnerText
                [String] $opcode = $e.RenderingInfo.Opcode

                if ($type -eq "PageFault") {
                    if ($opcode -eq "VirtualAlloc" –or 
                      $opcode -eq "VirtualFree") {
                        $ vmops++
                    }
                }
            }
            $hold.$pd = $vmops
        }
    }

    end {
        "{0,-20}|{1,-7}| VM Event Count" -f "Binar"," PID"
        "--------------------------------------------------------"
        
        $j = 0
        foreach ($e in ($hold.GetEnumerator() | Sort Value  -Descending)) {
            if ($j -lt $num) {
                $key = $e.Key
                "{0,-20} ({1,-6} {2}" -f $list.$key,"$($e.Key))",$e.Value
            } else {
                return
            }
            $j++
        }
    }
}

簡単なコア OS イベント分析のサンプル

ここでは、これまでに説明した OS イベントの一部を対象に、いくつか基本の集計手法を実際に示す簡単なスクリプトを紹介します。説明を簡単にするため Windows PowerShell スクリプトを使用しますが、基になるアルゴリズムをアプリケーションに取り入れて、より効率的な処理を行うこともできます。tracerpt ツールによって XML ダンプが作成されたら、次のコマンドを使用して、イベントをオブジェクトとして Windows PowerShell にインポートできます。

> $xmldata = New-Object System.Xml.XmlDocument
> $xmldata.Load(<XML ダンプ ファイル>)

1 つ目の Windows PowerShell スクリプト (図 1) は、プロセス イベントをスキャンして、ログ ファイルにすべてのプロセスを出力するだけのスクリプトです。ハッシュ テーブルにプロセス ID と名前のペアを書き込んで更新し、–print オプションが指定されている場合は、最後にこのテーブルを出力します。既定では、このペアの配列をパイプに渡して、他のスクリプトがこの結果を使用できるようにします。ここでは、サンプル スクリプトを簡単にするために、通常扱われる引数、コメント、およびエラー チェックの処理が省略されていることに注意してください。また、プロセス ID とスレッド ID は、このスクリプトのカーネル セッション中にリサイクルされないことを前提としていますが、実際にはこれらはリサイクルされます。正しい処理を行うには、追加のコードが必要です。

このスクリプトの結果は、XML ダンプにプロセス イベントが含まれていれば、図 2 のようになります。次のスクリプトの目的は、基本のステート マシンを作成することと、指定されたプロセス ID を使用して、そのプロセスに含まれるスレッドの数と読み込まれているイメージの一覧を出力することです。–i オプションまたは –t オプションが指定されている場合は、イメージ数とスレッド数ではなく、読み込まれているイメージの名前と、プロセスに含まれるスレッドの ID を出力します。図 3 はこの機能を実現するために作成されたスクリプト Get-ETW-PID-Info です。このスクリプトは、指定されたプロセス ID に関連するイベントのみを取得する Get-ETW-PID-Events (この記事には記載していません) という別のスクリプトを呼び出します。

次に、図 2 のメモ帳 (notepad) のプロセスを特定するため、Get-ETW-PID-Info スクリプトによる結果を取得しています。図 4 は、notepad.exe によって読み込まれているすべてのモジュールを列挙しています。

最後に、仮想メモリ操作数が最も多いプロセスのうち、上位 n 番目までのプロセスを示す表を出力します。Get-ETW-Top-VMops という名前のこのスクリプト (図 5 参照) では、Get-ETW-PID-List を実行して、プロセス ID の一覧を作成しています。次に、各プロセス ID を基にイベントをフィルター処理し、VM イベント数をカウントしています。最後に、並べ替えを行い、上位 n プロセスまでを示す表を出力しています。

最も仮想メモリ操作数が多いプロセスのうち上位 10 プロセスを示すこのスクリプトの結果は、図 6 のようになります。表には logman.exe のインスタンスとして、カーネル セッションの開始インスタンスと終了インスタンスの 2 つが含まれていることに注意してください。

図 6 Get-ETW-Top-VMops スクリプトの結果

PS C:\tests> $xml | Get-ETW-Top-Vmops 10
Binary              | PID   | VM Event Count
--------------------------------------------------------
svchost.exe          (536)   486
iexplore.exe         (3184)  333
svchost.exe          (1508)  206
logman.exe           (2836)  98
svchost.exe          (892)   37
sidebar.exe          (3836)  37
logman.exe           (1192)  19
svchost.exe          (2052)  18
audiodg.exe          (7048)  18
services.exe         (480)   13

ツールの機能を強化する

Windows 7 には、さまざまなコンポーネントのイベント プロバイダーが数百もあります。この 2 部構成のシリーズでは、Windows 7 が提供するコア OS ETW イベントと、長年使用してきた分析手法を紹介しました。個々のイベントは、コア OS の特定のアクティビティを示しますが、状況依存の分析方法を使用して組み合わせると、リソースの使用パターンや異常について洞察できる、意味のあるレポートを生成できます。また、これらのイベントのサブセットを効果的な方法で慎重に調査することで、専門研究分野での大きな発見につながっている場合がかなりあります。ETW 対応のアプリケーションでは、アプリケーションと OS のアクティビティを正確に関連付けられることから、さらにメリットが得られるでしょう。たとえば、アプリケーションが、重要なアプリケーション アクティビティの開始と終了を示すイベントを生成する場合、同時に収集されるコア OS イベントには、そのアクティビティに起因する OS リソース使用率についての正確な情報が含まれます。管理やパフォーマンスに関するツールの開発者は、コア システム イベントとさまざまな分析手法を利用して、開発するツールの機能を強化できます。これは、IT ワーカーにとってのメリットにつながります。アプリケーション開発者は、このような分析を各自の環境に組み込めば、アプリケーションの問題をより正確に分析できる可能性があります。この 2 部構成シリーズが、堅実なエンジニアリングの促進、ソフトウェア品質の向上、および優れたユーザー エクスペリエンスにつながればさいわいです。

Insung Park 博士は、Windows インストルメンテーションおよび診断プラットフォーム チームの開発マネージャーです。パフォーマンス分析、要求の追跡、インストルメンテーション テクノロジ、およびプログラミングの方法論とサポートについて、多数の論文を発表しています。連絡先は insungp@microsoft.com です。

Alex Bendetov は、Windows インストルメンテーションおよび診断プラットフォーム チームの開発リーダーです。Windows イベント トレーシングとパフォーマンス カウンター テクノロジの両方に携わっています。連絡先は alexbe@microsoft.com です。