製品コラム

セイテクエンジニアのブログ  製品コラム  メモリ/ハンドルリークを監視したい-BOM for Windows活用例

 

 

メモリ/ハンドルリークを監視したい-BOM for Windows活用例

2026年02月13日配信
執筆者:セイ・テクノロジーズ エバンジェリスト

 「BOM for Windows Ver.8.0」(以下、BOM)の「パフォーマンスカウンター監視」を使用すると、特定のパフォーマンスカウンターを簡単にしきい値監視できます。カウンター値に何かしらの計算加工を行って監視することもできます。それには「カスタム監視」を利用できます。

 

監視テンプレートによるパフォーマンス監視

 

 BOMが提供する豊富な監視テンプレートには、しきい値が定義済みのパフォーマンス監視項目が含まれており、開発元の知識と経験に基づいたしきい値、および場合によってはしきい値越えの継続性に基づいて適切な監視をすぐに開始できます。例えば、Windows用監視テンプレートに含まれる「システム監視」の「プロセッサ監視」は「Processor(_Total)¥% Processor Time」を監視するものです。この監視項目では、使用率90%で注意、3回連続して注意状態が続くと危険と評価するようにしきい値が設定されています。

 

 同じように、「システム監視」の「プロセッサ待ち行列長監視」は、パフォーマンスカウンター「System¥Processor Queue Length」を監視するものです。System¥Processor Queue Lengthは一般的に論理プロセッサ数×2を継続して超える場合、プロセッサがボトルネックと判断できます。監視テンプレートではこの値が10を超えると注意、3回連続して注意状態が続くと危険と評価するようにしきい値が設定されています(画面1)。より適切に監視するには、PowerShellで以下のいずれかのコマンドラインを実行し、それに2を掛けた数をしきい値(論理プロセッサ数8なら8×2=16)に設定するとよいでしょう。

 

(Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors

[Environment]::ProcessorCount

 

bommonleak_scr01
画面1 プロセッサ処理待ち行列長(System¥Processor Queue Length)のBOM既定のしきい値

 

メモリ/ハンドルリークの監視のためには上昇トレンドの監視が必要

 

 監視テンプレートに含まれないパフォーマンス監視については、「パフォーマンスカウンター監視」項目を作成して、特定のパフォーマンスカウンターを継続的に監視し、しきい値とその継続性に基づいてアラート通知することができます。カウンター値をそのままではなく、計算加工した上で監視することもできます。それには「カスタム監視」を使用します。

 例えば、パフォーマンスカウンター「Memory¥Pool Nonpaged Bytes」は、ディスクに退避できない、常に物理メモリ上に存在するメモリ量を示します。このカウンター値はその大きさよりも、時間とともに増え続ける、つまりメモリリークの疑いがないかどうかを監視するべきです。しかし、BOMはもちろん、Windowsのパフォーマンスモニターやその他の監視ツールでは、瞬間値に対するしきい値を設定することは可能でも、その上昇トレンドはグラフ表示など人が目視しなければ判断が難しいでしょう。同じように、パフォーマンスカウンター「Process(*または_Total)¥Handle Count」もハンドルリークを監視するにはその上昇トレンドを監視する必要があります。

 このような上昇トレンドの監視は、PowerShellのスクリプトで簡単に実装することができます。BOMの「カスタム監視」では、PowerShellスクリプトを含む外部コマンドの返す値を監視対象にできます。

 「Pool Nonpaged Bytes」とすべてのプロセスの「Handle Count」のカウンター値はPowerShellで次のコマンドラインを実行することで取得できます。

(Get-Counter "\Memory\Pool Nonpaged Bytes").CounterSamples.CookedValue
(Get-Counter "\Process(_Total)\Handle Count").CounterSamples.CookedValue

 

 次のPowerShellスクリプト「Get-PerfCounterTrend.ps1」は、引数に指定したパフォーマンスカウンターの値を取得し、テキストファイルに書き込んだ前回の値と比較して、増加していればその増分の値(今回の値-前回の値)を、同じまたは減少していれば0を返し、現在の値をテキストファイルに前回の値として書き込みます。前回の値のテキストファイルが存在しない初回実行時は、0(今回の値-今回の値)を返します。

 

[Get-PerfCounterTrend.ps1](プレーンテキストで表示)

param(
  [Parameter(Mandatory=$true)]
  [string]$Counter
)
if ($Counter -notlike "\*") {
  $Counter = "\" + $Counter
}
$tempFile = $Counter -Replace "\\","-"
$tempFile = $tempFile -Replace " ","_"
$tempFile = $tempFile -Replace "\*","asterisk"
$tempFile = "$env:temp\prev" + $tempFile + ".txt"
$curr = (Get-Counter $Counter -ErrorAction SilentlyContinue).CounterSamples.CookedValue
if ($curr -eq $null) {
 throw "Counter ($($Counter)) not found"
}

if (Test-Path $tempFile) {
  $prev = [int](Get-Content $tempFile -ErrorAction SilentlyContinue)
} else {
  $prev = $curr
}
$curr | Set-Content $tempFile 
if ($curr -gt $prev) {
  return [int]($curr - $prev)
} else {
  return 0
}

 

 このPowerShellスクリプトを、BOMの「カスタム監視」を使用して、powershell.exeで次のように実行するように設定し、しきい値を適切に設定すれば、メモリリークやハンドルリークの疑いを監視できるようになります(画面2、画面3)。

powershell.exe -ExecutionPolicy Bypass -File パス\Get-PerfCounterTrend.ps1 "<パフォーマンスカウンター>"

 

画面2 メモリリーク監視用のカスタム監視の設定
画面2 メモリリーク監視用のカスタム監視の設定

 

画面3 ハンドルリーク監視用のカスタム監視の設定
画面3 ハンドルリーク監視用のカスタム監視の設定

 しきい値設定は、例えば、0より大きい(前回から増加)なら注意のしきい値を設定し、さらにその状態が12回連続して続いた場合は危険とするように設定します。この監視項目を5分間隔で実行する場合、1時間(60)分間上昇傾向が続くと危険とみなします(画面4、画面5)。

 

 画面4 メモリリーク、ハンドルリークのしきい値の設定例
画面4 メモリリーク、ハンドルリークのしきい値の設定例

 

プロセスの最大/平均ハンドル数も併せて監視したい

 

 特定のプロセスを指定しない場合、パフォーマンスカウンター「Handle Count」で取得できるのは、システム全体の総ハンドル数です。1プロセスが開くことができるハンドル数の最大は理論上、約1600万(224=16,777,216)ですが、他のリソースの状況(非ページプールのサイズなど)の影響で、実際には理論値までのハンドルは作成できません。一般的に1つのプロセスで開いているハンドル数が数万というのは正常ですが、10万を超える状況が続くようなら注意するべきです。以下のPowerShellのコマンドラインは、それぞれ「Handle Count」の平均と最大を取得します。このコードを含むPowerShellスクリプト(.ps1)を「カスタム監視」で実行させることで、上昇トレンド(前述の監視)に加えて、異常な数のハンドル数を監視することができるでしょう(しきい値の例、5万以上で注意、10万上で危険)。上昇トレンドと最大/平均の両方が危険の状態は、ハンドルリークの疑いが高いと言えます。

 

プロセスが開いているハンドルの平均(総ハンドル数/プロセス数)を取得するPowerShellコード

$ret = (Get-Counter '\Process(_Total)\Handle Count').CounterSamples.CookedValue / (Get-Counter '\System\Processes').CounterSamples.CookedValue
[int]$ret

 

1つのプロセスで開いている最大のハンドル数を取得するPowerShellコード

$ret = (Get-Counter '\Process(*)\Handle Count' | Select-Object -ExpandProperty CounterSamples |
  Where-Object InstanceName -ne '_Total' | Sort-Object CookedValue -Descending |
  Select-Object -First 1).CookedValue
[int]$ret

 

 監視項目を作成したら、期待通りに機能するかテストします。メモリリークのシミュレーションにはWindows SysinternalsのNotMyFaultやTestLimitを、ハンドルリークのシミュレーションにはTestLimitを使用できます(画面5)。

 

NotMyFault|Sysinternals(Microsoft Learn)
TestLimit|Sysinternals(Microsoft Learn)

bommonleak_scr05-1

画面5 カスタム監視によりメモリリークやハンドルリークの疑いを検知したところ(NotMyFaultとTestLimitを利用してシミュレート)

 

関連:

ネットワークポートの枯渇を監視したい-BOM for Windows活用例|製品コラム

blog_column_subscribe

blog_column_comment

最新記事