JavaScriptを有効にしてください

Powershellでプロセスのメモリ使用量をロギングする

 ·   5 min read

はじめに

PowerShellのGet-Processコマンドレットを使って、特定のプロセスのメモリ使用量を一定周期でロギングするコードを作成した。

ロギング用スクリプト

特定のプロセスのメモリ使用量を一定周期で取得し、テキストファイルにCSV形式で保存するコードは以下の通り。
ただし、同じ名前の複数のプロセスが起動しているときには、それらのプロセスのメモリ使用量を合計する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$FileName = "log.txt"
$ProcessName = "notepad"

"Time,Working set(MB)" | Out-File -Append $FileName
while($TRUE){
    $d = Get-Date -Format "yyyy-MM-dd HH:mm:ss.ff"
    $p = Get-Process -Name $ProcessName | Select-Object WS
    $p | ForEach-Object {$mem = 0} {$mem += $_.WS}
    $mem = ($mem/1024/1024).ToString()
    $d+','+$mem | Out-File -Append $FileName
    Start-Sleep -Seconds 1
}

ここで、$FileNameは保存ファイル名、$ProcessNameは取得するプロセス名である。また、Start-Sleep -Secondsで実行周期を秒単位で指定する。
コードを停止する場合には、Ctrl+Cを押す。

実行すると、以下のようなCSV形式のファイルが出力される。

Time,Working set(MB)
2020-09-27 14:57:02.30,95.5
2020-09-27 14:57:03.32,94.4609375
2020-09-27 14:57:04.34,95.5
2020-09-27 14:57:05.37,95.5234375
2020-09-27 14:57:06.40,94.53515625
2020-09-27 14:57:07.43,94.53515625
2020-09-27 14:57:08.45,94.5234375
2020-09-27 14:57:09.49,95.5625

以下、スクリプトを解説する。

ファイルの保存(Out-File)

コマンドの出力をファイルに保存するには、Out-Fileコマンドレットを用いる。

1
2
Get-Process | Out-File output.txt
Get-Process | Out-File -Append output.txt

上記のように、文字列(または別のコマンド)をパイプラインでOut-Fileに与えることで、出力を指定した名前のファイルに保存できる。
また、-Appendオプションを付けると、出力をファイルの末尾に追加する。

時刻の取得(Get-Date)

システムの時刻を取得するには、Get-Dateコマンドレットを用いる。
Get-Dateコマンドレットにオプションを付けない場合、戻り値はSystem.DateTimeオブジェクトになる。
一方、-Formatオプションを追加すると戻り値は文字列になる。

1
$d = Get-Date -Format "yyyy-MM-dd HH:mm:ss.ff"

この例におけるフォーマットの意味は以下の通り。

フォーマット 説明
yyyy 4桁の西暦年
MM 2桁の月
dd 2桁の日
HH 2桁の時間
mm 2桁の分
ss 2桁の秒
ff 秒の端数(ミリ秒)の上位2桁

メモリ使用量の取得(Get-Process)

Get-Processコマンドレットを実行すると、プロセスのメモリ使用量などを取得できる。

1
2
3
4
5
6
PS > Get-Process
Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    855      44    40696      86404     106.11   3828  12 Code
    330      17     3972      20736       0.50   6928  12 notepad
    345      18     4116      21216       0.23   7432  12 notepad

Get-Process-NameオプションでProcessNameのプロセス名を指定すると、そのプロセスのみの結果が得られる。

1
2
3
4
5
PS > Get-Process -Name notepad
Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    330      17     3972      20736       0.50   6928  12 notepad
    345      18     4116      21216       0.23   7432  12 notepad

プロセスのメモリ使用量はWS(ワーキングセット)であり、この値を取得するにはSelect-Objectを用いる(WSを取得する理由については後述)。

1
2
3
4
5
PS > Get-Process -name notepad | Select-Object WS
      WS
      --
21139456
21630976

上記の例のように、プロセスが複数起動している場合は戻り値が複数あるので、それらを合計する(ただし、単位がバイトになっていることに注意)。

1
2
$p = Get-Process -Name $ProcessName | Select-Object WS
$p | ForEach-Object {$mem = 0} {$mem += $_.WS}

ForEach-Objectを使って、%pの各要素からWSの値を.WSプロパティを使って取り出している。また、WSの合計値は$memに格納される。

(補足)メモリ使用量の種類

Get-Processで取得できるメモリ使用量には、次の3種類がある。

  • NPM (Nonpaged System Memory)
  • PM (Paged Memory)
  • WS (Working Set)

正式名称を見てもこれらの違いは分かりづらいが、タスクマネージャの説明が分かりやすかったので、ここに記載する。

タスクマネージャの「詳細」タブを開き、表のヘッダを右クリックして「列の選択」を押し、以下の項目を表示させる。

  • 非ページプール
  • コミットサイズ
  • ワーキングセット(メモリ)

表示した項目と、Get-ProcessのNPM, PM, WSはそれぞれ以下の表の値が等しいことから、同じものを指していることが分かる。

Get-Process タスクマネージャ
NPM 非ページプール
PM コミットサイズ
WS ワーキングセット(メモリ)

さらに、タスクマネージャで表示した項目のヘッダにマウスカーソルを置くと、次の説明が表示される。

  • 非ページプール:プロセスの代わりにカーネルまたはドライバーによって割り当てられた、ページング不可能なカーネルメモリの量
  • コミットサイズ:プロセス用にオペレーティングシステムによって予約されている仮想メモリの量
  • ワーキングセット(メモリ):プロセスによって現在使用されている物理メモリの量

タスクマネージャのメモリ使用量表示

したがって、プロセスが使用しているメモリ使用量としては、ワーキングセット(WS)を見ればよいことが分かる。

参考

Get-Processについて
PowerShell - Powershellのpsコマンドで表示されるプロセスの情報の意味|teratail
逆引き!PowerShellでプロセスを取得する方法は?その見方は?【Get-Process】 | 【チェシャわら】PowerShellとは、から学ぶ入門者の教科書-脱コマンドプロンプト-

メモリのワーキングセットについて
第4回 メモリ管理:Windows OS入門 - @IT

シェアする

Helve
WRITTEN BY
Helve
関西在住、電機メーカ勤務のエンジニア。Twitterで新着記事を配信中です