Lee_Daily's helpful answer 讨论了重要的与构建数组(集合)有关的一般优化技术。
难题的另一个重要部分是尽可能避免在循环中调用(多个)cmdlet。
使用[random] (System.Random) 替换Get-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 的加速因子。
基准测试:
以下是与您的原始方法、Lee 的优化版本以及上面基于[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 function:
$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
}
}