2016-10-19 22 views
0

請參見下面的代碼,這兩個腳本的唯一區別在於第二個腳本塊中缺少腳本塊,並且由於它而導致性能顯着提高。Powershell性能與對象?

這是有原因嗎?是比其他人更強大的PowerShell嗎?

我正在做大量的腳本,其中有很多類似的塊,並且希望得到一個合理的答案,以便獲得簡單的性能提升,比如這個,那麼爲什麼要排除scriptblock中的Where-Object(別名?)突然將性能降低了一個可觀的餘量?

PS C:\Scripts> $a = 1..15 | % { 
    Measure-Command { 
     $G = Get-ADGroup -Filter * 
     1..3 | % { 
      $G | ? {$_.Name -eq "TestGroup$($_)"} 
     } 
    } 
} 

$b = 1..15 | % { 
    Measure-Command { 
     $G = Get-ADGroup -Filter * 
     1..3 | % { 
      $G | ? Name -eq "TestGroup$($_)" 
     } 
    } 
} 

($a.TotalMilliseconds | Measure -Average).Average 
($b.TotalMilliseconds | Measure -Average).Average 

283.479413333333 
212.57384 
+0

實際上,差別要大得多。要隔離它,請將'$ G'分配移出測量,並使用更大的內部循環,如'1..1e5'。 – wOxxOm

+1

不要挑剔,而是爲了避免混淆:它不會「削減績效」_。它可以「縮短運行時間」或「提高性能」。選一個。 :-) –

回答

0

PowerShell的3.0引入Where-Object(別名:Where?),其可直接檢查屬性,而無需一個腳本塊。

執行腳本塊時像任何其他語言一樣,PowerShell創建一個新的執行上下文,並且在解釋型語言中它非常昂貴。

使用舊的符號與腳本塊的唯一理由是:

  • 有PS1/PS2兼容的代碼;
  • 執行復雜的檢查;
  • 做除了檢查本身之外的東西。

至於你的代碼,這兩個片段在其他地方使用scriptblocks,流水線(這比foreach聲明慢5-10倍),以及不必要的測量Get-ADGroup時間,所以我們可以優化它更:

$group = Get-ADGroup -Filter * 
$c = foreach ($i in 1..15) { 
    Measure-Command { 
     foreach ($j in 1..3) { 
      $filtered = foreach ($g in $group) { if ($g.Name -eq "TestGroup$($j)") { $g } } 
     } 
    } 
} 

有時,通過準備數據可以獲得更大的收益。例如,如果在循環中重複檢查某些對象數組以查看它是否具有某個屬性值,最好將該數組轉換爲具有基於該屬性值的鍵的散列表:

# index by somefield 
$lookup = @{} 
foreach ($element in $array) { $lookup[$element.somefield] = $element } 

# use the indexed lookup table 
foreach ($element in $anotherarray) { 
    $existingElement = $lookup[$element.somefield] 
    if ($existingElement) { 
     # do something 
    } 
}