回答:
うん。
Measure-Command { .\do_something.ps1 }
のマイナーな欠点の1つMeasure-Command
は、stdout
出力が表示されないことです。
[更新、@ JasonMArcherのおかげで]ホストに書き込むコマンドレットにコマンド出力をパイプすることで修正できます。たとえばOut-Default
、次のようになります。
Measure-Command { .\do_something.ps1 | Out-Default }
出力を確認する別の方法は、次のStopwatch
ような.NET クラスを使用することです。
$sw = [Diagnostics.Stopwatch]::StartNew()
.\do_something.ps1
$sw.Stop()
$sw.Elapsed
time { ping -n 1 google.com } -Samples 10
コマンド10
時間を実行し、かかった平均時間、最小時間、最大時間を返します。-Silent
STDOUTを飲み込むことができます。
$t = Measure-Command {<<your command or code block>>}
です。それを試してみて、次に入力し$t
、あなたの結果、あなたのような、へのアクセス権を持つすべてのプロパティを表示するプロンプトで$t.Milliseconds
、$t.TotalSeconds
、その後、我々は、例えば、私たちが望むものは何でも出力に書き込むことができるなど、Write-Host That command took $t.TotalSeconds to complete.
また、履歴から最後のコマンドを取得し、そのを引くことができEndExecutionTime
、そのからStartExecutionTime
。
.\do_something.ps1
$command = Get-History -Count 1
$command.EndExecutionTime - $command.StartExecutionTime
Get-History | Group {$_.StartExecutionTime.Hour} | sort Count -desc
ください。PowerShellの使用パターンを時間ごとに確認できます。:-)
$command = Get-History -Count 1 ; "{0}" -f ($command.EndExecutionTime - $command.StartExecutionTime)
使用する Measure-Command
例
Measure-Command { <your command here> | Out-Host }
パイプをOut-Host
使用すると、コマンドの出力を確認できます。この出力は、通常はによって使用されMeasure-Command
ます。
Measure-Command {<your command } | Out-Host
-アウト・ホストは、スクリプトブロックの外にある
シンプル
function time($block) {
$sw = [Diagnostics.Stopwatch]::StartNew()
&$block
$sw.Stop()
$sw.Elapsed
}
その後、次のように使用できます
time { .\some_command }
あなたは出力を微調整したいかもしれません
Measure-Command
コマンド出力を非表示にするため、このソリューションの方が良い場合があります。
Unix time
コマンドと同様に機能する、私が作成した関数は次のとおりです。
function time {
Param(
[Parameter(Mandatory=$true)]
[string]$command,
[switch]$quiet = $false
)
$start = Get-Date
try {
if ( -not $quiet ) {
iex $command | Write-Host
} else {
iex $command > $null
}
} finally {
$(Get-Date) - $start
}
}
出典:https : //gist.github.com/bender-the-greatest/741f696d965ed9728dc6287bdd336874
Measure-Command
たり、さまざまな方法で実行したりするのではなく、自分で実行時間を計算する方法を示しています。元の質問を読んだ場合、彼は「time
Linux のコマンドのように」機能するものを求めました。
ストップウォッチの使用と経過時間のフォーマット:
Function FormatElapsedTime($ts)
{
$elapsedTime = ""
if ( $ts.Minutes -gt 0 )
{
$elapsedTime = [string]::Format( "{0:00} min. {1:00}.{2:00} sec.", $ts.Minutes, $ts.Seconds, $ts.Milliseconds / 10 );
}
else
{
$elapsedTime = [string]::Format( "{0:00}.{1:00} sec.", $ts.Seconds, $ts.Milliseconds / 10 );
}
if ($ts.Hours -eq 0 -and $ts.Minutes -eq 0 -and $ts.Seconds -eq 0)
{
$elapsedTime = [string]::Format("{0:00} ms.", $ts.Milliseconds);
}
if ($ts.Milliseconds -eq 0)
{
$elapsedTime = [string]::Format("{0} ms", $ts.TotalMilliseconds);
}
return $elapsedTime
}
Function StepTimeBlock($step, $block)
{
Write-Host "`r`n*****"
Write-Host $step
Write-Host "`r`n*****"
$sw = [Diagnostics.Stopwatch]::StartNew()
&$block
$sw.Stop()
$time = $sw.Elapsed
$formatTime = FormatElapsedTime $time
Write-Host "`r`n`t=====> $step took $formatTime"
}
使用サンプル
StepTimeBlock ("Publish {0} Reports" -f $Script:ArrayReportsList.Count) {
$Script:ArrayReportsList | % { Publish-Report $WebServiceSSRSRDL $_ $CarpetaReports $CarpetaDataSources $Script:datasourceReport };
}
StepTimeBlock ("My Process") { .\do_something.ps1 }
回答で参照されているパフォーマンス測定コマンドのいずれかから(誤った)結論を導き出すことについてのちょっとした言葉。(カスタム)関数またはコマンドの最低限の呼び出し時間を確認することを除いて、考慮すべきいくつかの落とし穴があります。
「シェーメルソフト」が2015年のオランダ語で投票
シェーメーレンは不正行為を意味し、シェーメルソフトウェアという言葉はフォルクスワーゲンの排出スキャンダルが原因となった。公式の定義は「テスト結果に影響を与えるために使用されるソフトウェア」です。
個人的には、「Sjoemelsoftware」は必ずしも意図的にテスト結果をだますためのものではなく、以下に示すようなテストケースに似た現実的な状況から生まれたものだと思います。
例として、リストされているパフォーマンス測定コマンドであるLanguage Integrated Query(LINQ)(1)を使用すると、多くの場合、何かを実行するための高速な方法と見なされます。ネイティブのPowerShellコマンドと比較して40倍以上の速度の増加を測定する人は、おそらく誤った測定または誤った結論を出しているでしょう。
重要なのは、遅延評価を使用する一部の.Netクラス(LINQなど)(遅延実行(2)とも呼ばれる)です。つまり、式を変数に代入すると、ほとんどすぐに実行されたように見えますが、実際にはまだ何も処理していません。
PowerShellまたはより高度なLinq式のいずれかを含むコマンドをドットソース化するとします. .\Dosomething.ps1
(説明を簡単にするために、式を直接に直接埋め込みましたMeasure-Command
)。
$Data = @(1..100000).ForEach{[PSCustomObject]@{Index=$_;Property=(Get-Random)}}
(Measure-Command {
$PowerShell = $Data.Where{$_.Index -eq 12345}
}).totalmilliseconds
864.5237
(Measure-Command {
$Linq = [Linq.Enumerable]::Where($Data, [Func[object,bool]] { param($Item); Return $Item.Index -eq 12345})
}).totalmilliseconds
24.5949
結果は明らかです。後のLinqコマンドは、最初のPowerShellコマンドよりも約40倍高速です。残念ながら、それはそれほど簡単ではありません ...
結果を表示しましょう:
PS C:\> $PowerShell
Index Property
----- --------
12345 104123841
PS C:\> $Linq
Index Property
----- --------
12345 104123841
予想どおり、結果は同じですが、細心の注意を払っている場合は、$Linq
結果を表示するよりも結果を表示するのに時間がかかることに気づくでしょう$PowerShell
。結果のオブジェクトのプロパティを取得するだけで
具体的に測定します。
PS C:\> (Measure-Command {$PowerShell.Property}).totalmilliseconds
14.8798
PS C:\> (Measure-Command {$Linq.Property}).totalmilliseconds
1360.9435
オブジェクトのプロパティを取得するのに約90倍長い時間がかかりましたが、$Linq
それは$PowerShell
オブジェクトだけでした。
また、もう一度実行すると、一部のステップが以前よりもはるかに速く表示される可能性があるという他の落とし穴にも注意してください。これは、一部の式がキャッシュされているためです。
結論として、2つの関数のパフォーマンスを比較したい場合は、使用した場合にそれらを実装し、新しいPowerShellセッションから始めて、ソリューション全体の実際のパフォーマンスに基づいて結論を出す必要があります。
(1)PowerShellとLINQの背景と例については、次のサイトをお勧めします:LINQを使用した高性能PowerShell
(2)遅延評価の場合、結果は必要に応じて計算されるため、2つの概念には小さな違いがあると思いますシステムがアイドル状態のときに結果が計算される遅延実行