はじめに #
PowerShellのGet-Process
コマンドレットを使って、特定のプロセスのメモリ使用量を一定周期でロギングするコードを作成した。
ロギング用スクリプト #
特定のプロセスのメモリ使用量を一定周期で取得し、テキストファイルにCSV形式で保存するコードは以下の通り。 ただし、同じ名前の複数のプロセスが起動しているときには、それらのプロセスのメモリ使用量を合計する。
$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
コマンドレットを用いる。
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
オプションを追加すると戻り値は文字列になる。
$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
コマンドレットを実行すると、プロセスのメモリ使用量などを取得できる。
例
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
のプロセス名を指定すると、そのプロセスのみの結果が得られる。
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を取得する理由については後述)。
PS > Get-Process -name notepad | Select-Object WS
WS
--
21139456
21630976
上記の例のように、プロセスが複数起動している場合は戻り値が複数あるので、それらを合計する(ただし、単位がバイトになっていることに注意)。
$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とは、から学ぶ入門者の教科書-脱コマンドプロンプト-
メモリのワーキングセットについて