tech.guitarrapc.cóm

Technical updates

PowerShellでNull破棄する際に最も適したやり方を探る

Powershellが遅いなら、コストのかからない方法を考えよう特集第四弾です。

PowerShellでFor / Foreach / Foreach-Object / ScriptBlock / Filterのベンチマーク In English : PowerShell For / Foreach / Foreach-Object / ScriptBlock / Filter – Benchmark 2013 PowerShellのForeach-Objectは一体何をしているのか PowerShellでSubstitute(変数代入)、Host(ホスト出力)、Content(ファイル出力)するコストのベンチマーク

PowerShellで結果がホスト表示される時にNull破棄をしたいことは多々あります。 そして、Null破棄はやり方が色々あります。 そこで、今回はNull破棄で最もコストがかからず実行速度に影響を与えない方法を考えてみます。

UserVoice にもあったりしたり。

 

Please feel free to provide feedback or file bugs here. Unlike other Windows Server UserVoice forums, the PowerShell forum accepts bug reports.
  • 3 votes
  • 0 comments

performance of out-null drastically worse then using [void] or assigning result to $null

Votes from Connect: 4

Original Date Submitted: 3/28/2015 6:08:31 AM

Description:
********Contact Information********
Handle: JasonHorner
Site Name: PowerShell
Feedback ID: 1208677
***************************************

Frequency: PowerShell
Regression: gci | out-null
[void](gci)...

windowsserver.uservoice.com

Null破棄をする方法

まずNull破棄をする手段を考えてみましょう。

{ScriptBlock} | Out-Null
[Void]{ScriptBlock}
{ScriptBlock} > $null
$null = {ScriptBlock}

以上の4つがぱっと思いつきます。

テストコード

では、それぞれのベンチマークを取ることでコストを考えます。 テスト1 以下のコードで1..1000を生成実行する際のベンチを10000回実行して平均を取りました。

# Null破棄しない
1..10000 | ForEach-Object{
    [double](Measure-Command {$(1..1000)} | select -ExpandProperty TotalMilliseconds)
} | Measure-Object -Average

# | out-Null
1..10000 | ForEach-Object{
    [double](Measure-Command {$(1..1000) | Out-Null} | select -ExpandProperty TotalMilliseconds)
} | Measure-Object -Average

# [void]
1..10000 | ForEach-Object{
    [double](Measure-Command {[Void]$(1..1000)} | select -ExpandProperty TotalMilliseconds)
} | Measure-Object -Average

# > $null
1..10000 | ForEach-Object{
    [double](Measure-Command {$(1..1000) > $null} | select -ExpandProperty TotalMilliseconds)
} | Measure-Object -Average

# $null =
1..10000| ForEach-Object{
    [double](Measure-Command {$null = $(1..1000)} | select -ExpandProperty TotalMilliseconds)
} | Measure-Object -Average

テスト2 以下のコードは、1..1000を生成し、[int]型チェックする際のベンチを10000回実行して平均を取りました。

# Null破棄しない
1..10000 | ForEach-Object{
    [double](Measure-Command {$(1..1000) | where {$_ -is [int]}} | select -ExpandProperty TotalMilliseconds)
} | Measure-Object -Average

# | out-Null
1..10000 | ForEach-Object{
    [double](Measure-Command {$(1..1000) | where {$_ -is [int] | Out-Null}} | select -ExpandProperty TotalMilliseconds)
} | Measure-Object -Average

# [void]は、Cast出来ないため省きます。

# > $null
1..10000 | ForEach-Object{
    [double](Measure-Command {$(1..1000) | where {$_ -is [int]> $null}} | select -ExpandProperty TotalMilliseconds)
} | Measure-Object -Average

# $null =
1..10000| ForEach-Object{
    [double](Measure-Command {$null = $(1..1000)  | where {$_ -is [int]}} | select -ExpandProperty TotalMilliseconds)
} | Measure-Object -Average

ベンチ結果

ベンチ結果です。

Null Operation Test1 Test2
None 0.29 95.93
Out-Null 21.59 224.24
[void] 0.19 -
> $null 0.17 100.04
$null = 0.22 99.10

 

まとめ

以上から、Null破棄する際に | Out-Nullをすることはもってのほかと分かります(おい ついパイプでつなげられるので使ってしまうのですが…… > $nullが読みやすさも良いですねー。 [void]は型変換できないパターンが多いので、Add-Typeとかぐらいにですかねーw いずれにしても、| Out-Nullさえつかわなければ問題なさそうなので良かったですね。

参考サイト

Whats the better (cleaner) way to ignore output in PowerShell