Полезный ответ Lee_Daily обсуждает важные общие методы оптимизации в отношении построения массивов (коллекций) .
Еще одна важная часть головоломки - избегать(несколько) вызовов командлетов внутри цикла , если это возможно.
Замена вызовов Get-Random
с использованием [random]
(System.Random
) обеспечивает наибольшее ускорение (PSv5 +синтаксис):
$ArrayDataRows = 150000
$places = 'NJ', 'UT', 'NY', 'MI', 'PA', 'FL', 'AL', 'NM', 'CA', 'OK', 'TX', 'CO', 'AZ'
$colors = 'red', 'yellow', 'blue', 'purple', 'green', 'white', 'black'
$chars = [char[]] (65..90)
$nums = 1..20
# Instantiate a random number generator.
$rndGen = [random]::new()
$ArrayData = foreach ($i in 1..$ArrayDataRows) {
[PSCustomObject] @{
Number = $i
Place = $places[$rndGen.Next(0, $places.Count)]
Color = $colors[$rndGen.Next(0, $colors.Count)]
Zone = -join $(
$charList = [Collections.Generic.List[char]]::new($chars)
foreach ($n in 1..10) { $randIndex = $rndGen.next(0, $charList.count); $charList[$randIndex]; $charList.RemoveAt($randIndex) }
)
Group = $nums[$rndGen.Next(0, $nums.Count)]
}
На моей машине вышеупомянутое занимает около 12 секунд, тогда как ваша исходная команда выполнялась в течение 35 минут (!), что составляет коэффициент ускорения около 175 * 1020.*.
Тесты :
Ниже приведены примеры времени, которые контрастируют с вашим первоначальным подходом, оптимизированной версией Ли и решением на основе [random]
.выше;абсолютные числа не важны, но относительная производительность, как показано в столбце Factor
:
с 1000
элементами массива:
Factor Secs (10-run avg.) Command
------ ------------------ -------
1.00 0.100 # with [random]…
12.78 1.273 # with Get-Random - optimized…
13.45 1.340 # with Get-Random - original approach…
Обратите внимание, что при 1000 элементахОптимизация подхода построения массива обеспечивает некоторое, но не огромное ускорение, но преимущество тем больше, чем больше элементов.
С 10,000
элементами массива:
Factor Secs (10-run avg.) Command
------ ------------------ -------
1.00 1.082 # with [random]…
12.29 13.296 # with Get-Random - optimized…
20.40 22.081 # with Get-Random - original approach…
С 10 000 элементов оптимизация построения массива уже окупается.
У меня не хватило терпения работать с 150,000
элементами, но легко адаптировать следующий код, который использует Time-Command
функция :
$ArrayDataRows = 1000
$places = 'NJ', 'UT', 'NY', 'MI', 'PA', 'FL', 'AL', 'NM', 'CA', 'OK', 'TX', 'CO', 'AZ'
$colors = 'red', 'yellow', 'blue', 'purple', 'green', 'white', 'black'
$chars = [char[]] (65..90)
$nums = 1..20
Time-Command -Count 10 { # with [random]
# Instantiate a random number generator.
$rndGen = [random]::new()
$ArrayData = foreach ($i in 1..$ArrayDataRows) {
[PSCustomObject] @{
Number = $i
Place = $places[$rndGen.Next(0, $places.Count)]
Color = $colors[$rndGen.Next(0, $colors.Count)]
Zone = -join $(
$charList = [Collections.Generic.List[char]]::new($chars)
foreach ($n in 1..10) { $randIndex = $rndGen.next(0, $charList.count); $charList[$randIndex]; $charList.RemoveAt($randIndex) }
)
Group = $nums[$rndGen.Next(0, $nums.Count)]
}
}
}, { # with Get-Random - optimized
$ArrayData = foreach ($i in 1..$ArrayDataRows) {
[PSCustomObject] @{
Number = $i
Place = Get-Random -InputObject $places
Color = Get-Random -InputObject $colors
Zone = -join (Get-Random -InputObject $chars -Count 10)
Group = Get-Random -InputObject $nums
}
}
} ,{ # with Get-Random - original approach
$ArrayData = @()
foreach ($i in 1..$ArrayDataRows) {
$thisobject = [PSCustomObject] @{
Number = $i
Place = Get-Random -InputObject $places
Color = Get-Random -InputObject $colors
Zone = -join (Get-Random -InputObject $chars -Count 10)
Group = Get-Random -InputObject $nums
}
$ArrayData += $thisobject
}
}