Arrays Powershell—创建非常大的哈希表数组的最快方法
我试图创建一个相当大的哈希表数组,其中大部分数据要么完全随机,要么从列表中随机选取 这是我的当前代码Arrays Powershell—创建非常大的哈希表数组的最快方法,arrays,performance,powershell,optimization,hashtable,Arrays,Performance,Powershell,Optimization,Hashtable,我试图创建一个相当大的哈希表数组,其中大部分数据要么完全随机,要么从列表中随机选取 这是我的当前代码 $ArrayData=@() $ArrayDataRows=150000 foreach($i在1..$ArrayDataRows中){ $thisobject=[PSCustomObject]@{ 数字=$i 地点=获取随机-输入对象NJ、UT、NY、MI、PA、FL、AL、NM、CA、OK、TX、CO、AZ 颜色=获取随机-输入对象红色、黄色、蓝色、紫色、绿色、白色、黑色 区域=(获取随机-
$ArrayData=@()
$ArrayDataRows=150000
foreach($i在1..$ArrayDataRows中){
$thisobject=[PSCustomObject]@{
数字=$i
地点=获取随机-输入对象NJ、UT、NY、MI、PA、FL、AL、NM、CA、OK、TX、CO、AZ
颜色=获取随机-输入对象红色、黄色、蓝色、紫色、绿色、白色、黑色
区域=(获取随机-InputObject$([char[]](65..90))-计数10)-加入“”
组=获取随机-输入对象@(1..20)
}
$ArrayData+=$thisobject
}
但我注意到,它似乎没有效率。总共需要25分钟才能完成15万排
我在这里没有发布一些额外的代码,这些代码测量了每个实例所用的时间,并估计了从它到它的前辈的平均时间。最初,我估计总数为450秒,前3k个项目的每个实例的平均值为0.002秒,但后来它只是缓慢地爬行到0.016秒或平均值的8倍
如何在获得相同数据的同时优化和/或提高效率?[编辑-您不是在创建哈希表数组。您是在创建PSCustomObject
项数组。[*grin*]]
标准阵列是一个固定大小的对象。查看$ArrayData.IsFixedSize
以确认这一点。[咧嘴笑]
因此,当您在标准阵列上使用+=
时,powershell会创建一个新的、一项较大的阵列,将旧阵列复制到新阵列中,最后添加新项目。当物品数量和大小为“小”时,速度很快,但随着数量/大小的增加,速度会变慢[越来越慢,越来越慢]
有两种常见的解决方案
- 使用具有
方法的集合类型.Add()
人们通常使用
[deprecated]和ArrayList
。当您添加到第1个时,它会输出一个索引号,因此即使它没有被弃用,我也不会使用它。[咧嘴笑]Generic.List
- 使用输出流
您可以使用
,脚本块的输出将保存在RAM中,直到循环完成。然后它将一次全部填充到$Results=foreach($Collection中的Thing){Do Stuff}
集合中李>$Results
$ArrayDataRows = 15e3
$PlaceList = 'NJ, UT, NY, MI, PA, FL, AL, NM, CA, OK, TX, CO, AZ'.Split(',').Trim()
$ColorList = 'red, yellow, blue, purple, green, white, black'.Split(',').Trim()
$UC_LetterList = [char[]](65..90)
$GroupList = 1..20
(Measure-Command -Expression {
$ArrayData = foreach ($i in 1..$ArrayDataRows) {
[PSCustomObject] @{
Number = $i
Place = Get-Random -InputObject $PlaceList
Color = Get-Random -InputObject $ColorList
Zone = -join (Get-Random -InputObject $UC_LetterList -Count 10)
Group = Get-Random -InputObject $GroupList
}
}
}).TotalMilliseconds
# total ms = 24,390
讨论有关构建阵列(集合)的重要通用优化技术
难题的另一个重要部分是尽可能避免循环中的(多个)cmdlet调用
使用[Random]
()替换Get Random
调用可提供最大的加速比(PSv5+语法):
在我的机器上,上面的命令大约需要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…
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…
请注意,在1000个元素时,阵列构建方法的优化提供了一些但不是很大的加速,但是元素越多,好处就越大
使用10000
数组元素:
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…
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…
有了10000个元素,阵列构建的优化已经获得了丰厚的回报
我没有耐心运行150000
元素,但是很容易适应以下代码,它使用:
IIRC,你的
@()
每次你+=
都在制作一份新的副本。使用[System.Collections.ArrayList]
和.Add()
,我敢打赌您的性能会提高。此外,对于所有这些inputObject,在循环外创建它们一次并存储在变量中。考虑到较小的尺寸,可以忽略不计,但仍然是一种优化。将内容放入集合的最快方法是使用$collection=foreach()
。。。这将收集RAM中的所有项,并最终将它们一次填充到$Collection
中。它实际上比ArrayList
&Generic.List
集合类型的.Add()
方法更快。[grin]另外,您并不是在制作哈希表数组。。。您正在创建PSCustomObjects数组。[咧嘴笑]