我正在處理大量資料,在提取資料并對其進行處理后,我將結果存盤在記憶體中的一個變數中。
我現在需要將這些資料分成單獨的變數,這很容易通過管道和使用 where-object 來完成,但是現在我有更多的資料(超過 100 萬成員),這已經減慢了速度。注意:大約需要 5 分鐘以上。
$DCEntries = $DNSQueries | ? {$_.ClientIP -in $DCs.ipv4address -Or $_.ClientIP -eq '127.0.0.1'}
$NonDCEntries = $DNSQueries | ? {$_.ClientIP -notin $DCs.ipv4address -And $_.ClientIP -ne '127.0.0.1'}
#Note:
#$DCs is an array of 60 objects of type Microsoft.ActiveDirectory.Management.ADDomainController, with two properties: Name, ipv4address
#$DNSQueries is a collection of pscustomobjects that has 6 properties, all strings.
我立即意識到我正在列舉 $DNSQueries(大物件)兩次,這顯然花費了我一些時間。因此,我決定采用不同的方式來列舉它一次并使用 Switch 陳述句,但這似乎以指數方式導致時間增加,這不是我想要的。
$DNSQueries | ForEach-Object {
Switch ($_) {
{$_.ClientIP -in $DCs.ipv4address -Or $_.ClientIP -eq '127.0.0.1'} {
# Query is from a DC
$DCEntries = $_
}
default {
# Query is not from DC
$NonDCEntries = $_
}
}
}
我想知道是否有人可以向我解釋為什么第二個代碼需要這么多時間。此外,也許提供一種更好的方法來完成我想要的。
Foreach-Object 和/或附加子變數是否花費那么多時間?
uj5u.com熱心網友回復:
ForEach-Objectswitch實際上是列舉集合的最慢方法,但還有一個后續script block條件會導致更多開銷。
如果集合已經在記憶體中,沒有什么比線性列舉foreach回圈更好的了。
至于你最大的問題,使用 =將元素添加到陣列并且它是一個固定大小的集合。每次添加新元素時,PowerShell 都必須創建一個新陣列并將所有元素復制到一個新陣列中,這會導致極高的開銷。有關更多詳細資訊,請參閱此答案以及此很棒的檔案。
在這種情況下,您可以結合Collections.Generic.List<T>使用 PowerShell 的顯式賦值。
$NonDCEntries = [Collections.Generic.List[object]]::new()
$DCEntries = foreach($item in $DNSQueries) {
if($item.ClientIP -in $DCs.IPv4Address -Or $_.ClientIP -eq '127.0.0.1') {
$item
continue
}
$NonDCEntries.Add($item)
}
要了解陣列的指數級損壞 =程度,您可以測驗此代碼:
$Tests = [ordered]@{
'PowerShell Explicit Assignment' = {
$result = foreach($i in 1..$count) {
$i
}
}
' = Operator to System.Array' = {
$result = @( )
foreach($i in 1..$count) {
$result = $i
}
}
'.Add(..) to List<T>' = {
$result = [Collections.Generic.List[int]]::new()
foreach($i in 1..$count) {
$result.Add($i)
}
}
}
foreach($count in 1000, 10000, 100000) {
foreach($test in $Tests.GetEnumerator()) {
$measurement = (Measure-Command { & $test.Value }).TotalMilliseconds
$totalRound = [math]::Round($measurement, 2).ToString() ' ms'
[pscustomobject]@{
CollectionSize = $count
Test = $test.Key
TotalMilliseconds = $totalRound
}
}
}
在我的筆記本電腦中產生以下結果:
CollectionSize Test TotalMilliseconds
-------------- ---- -----------------
1000 PowerShell Explicit Assignment 15.9 ms
1000 = Operator to System.Array 26.88 ms
1000 .Add(..) to List<T> 12.47 ms
10000 PowerShell Explicit Assignment 1.07 ms
10000 = Operator to System.Array 2488.24 ms
10000 .Add(..) to List<T> 0.9 ms
100000 PowerShell Explicit Assignment 16.07 ms
100000 = Operator to System.Array 308931.8 ms
100000 .Add(..) to List<T> 8.39 ms
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/534698.html
標籤:电源外壳管道枚举
