読者です 読者をやめる 読者になる 読者になる

HYPERCONCERTO株式会社のチーフエンジニア雑記Blog

hyperconcerto株式会社のチーフエンジニアが日々気づいたことを書いています

4回目、vSphereをPowerShellで操作するときのTips

PowerCLIの実行速度が遅いんですが…

回答
PowerCLI 6.5 R1なら早いですよ。
実は6.5からは最初から最適化済みのモジュールがインストールされるので実行速度が上がっています。
というわけで調べてみました。

下記コマンドを実行
Measure-Command { get-vm }

6.0の32bit版で最適化無
約3.5秒

6.5の32bit版でインストール直後
約0.8秒

6.0までは32bit版が速かったのですが、6.5からは64bit版の方が速いみたい。

参考
6.5の64bit版でインストール直後
約0.45秒

いままでの6.0は最適化されていないのか?という疑問がありますが、最適化されていません。
詳細は下記記事を参照
https://blogs.vmware.com/PowerCLI/2011/06/how-to-speed-up-the-execution-of-the-first-powercli-cmdlet.html

6.0の最適化自体は下記コマンドで実行できます。
C:\Windows\Microsoft.NET\Framework\v4.0.30319\ngen.exe install “VimService60.XmlSerializers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=10980b081e887e9f”
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\ngen.exe install “VimService60.XmlSerializers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=10980b081e887e9f”

動きとしてはngen.exeでネイティブイメージを生成してグローバルアセンブリに登録するという動きをします。

次はスクリプトの書き方による実行速度の違いを解説します。

●書き方による速度の違い

同じ出力を得ることができますが、いくつかの書き方ができます。

例1
Measure-Command { $ret = get-vm;$ret | where { $_.Name -eq "testvm-01" }}
約2秒

例2
Measure-Command { get-vm | where { $_.Name -eq "testvm-01" }}
約1.9秒

例3
Measure-Command { get-vm -name testvm-01 }
約0.5秒

例1はfor文で拾う時用ですね。
当然ですが、Get-VMの-Name引き数で指定したほうが速いです。


ループの場合

下記のような書き方にすると遅くなることが多いです。

あかん例
foreach ($tempList in $VMList){
Get-VM -Name $tempList
}

改善した例
$ret = Get-VM
foreach ($tempList in $VMList){
$ret | where { $_.Name -eq $tempList }
}

$VMListに入っている数が数個ならいいのですが10個を超えるとかなり遅くなります。

基本的にPowerShellは実行速度が結構遅いので、書き方に注意が必要です。
Where-Object句自体がちょっと遅い気がします。

その他の遅いと苦情を言われるパターン
PowerCLIのモジュールを使うps1ファイルの場合ですが、PowerCLI自体のモジュールのロードが遅いです。
数分かかることもありますので、頻繁に実行するのならプロセスを上げたままで処理するなどの工夫が必要です。