昨晚我玩了一些用PowerShell编写的排序算法。事先我必须生成一个随机整数数组,以便可以进行排序。但是,生成数组的时间使我花费了太长时间,因此我改进了代码以使其尽可能快地运行。
我的最终代码如下:
$max = 1000000
$RndNumberArr = New-Object System.Collections.ArrayList
$ran = New-Object Random
for ($i = 0; $i -lt $max; $i++)
{
[void]$RndNumberArr.Add($ran.Next(0,$max))
}
使用Measure-Command,我的平均执行时间约为2.5秒。
我注意到使用ArrayList
比使用固定大小的数组要快(对我来说这没有多大意义,有更快的东西吗?)
此外,使用.NET方法random.Next()
代替CMDLet Get-Random
也可以提高速度(节省30秒)。
使用.NET方法有什么缺点吗?
我也认为使用
[void]$RndNumberArr.Add($ran.Next(0,$max))
为防止Array.Add
输出比使用
$RndNumberArr.Add($ran.Next(0,$max)) > $null
我对吗?
CMDLet具有明显的时差,是最慢的。
$RndNumberArr.Add($ran.Next(0,$max)) | Out-Null
我的计算机硬件(特别是CPU)是否会影响PowerShell的执行速度,或者速度是否在某个时候受到限制?如果是这样,是否有办法增强分配的系统资源以提高速度?
非常感谢。
答案 0 :(得分:2)
如果您的目标是生成大量随机整数,则建议完全避免列表管理:
$r = [Random]::new()
$max = 1000000
$list = foreach ($i in 1..$max)
{
$r.Next(0, $max)
}
与使用for
循环相比,此代码的运行速度几乎快一倍(大约1.4-1.5秒和2.6秒)。
答案 1 :(得分:2)
TheIncorrigible1's helpful answer提供最快的解决方案,有两个原因:
通过隐式收集foreach
循环的所有输出,它使 PowerShell 为您构造数组。
它将 range语法与foreach
(1..$max
)结合使用,而不是使用算术的for
循环;尽管使用范围语法的foreach
循环会消耗更多的内存-索引数组必须预先构建为一个整体-明显比算术for
循环要快。
我注意到使用ArrayList比使用固定大小的Array更快
那是因为 .NET数组是 fixed-size 个集合,所以您不能添加个元素到数组中以迭代地构造它。
PowerShell通过允许您执行 $array += ...
来向您隐藏该事实,但是在幕后要做的就是每次创建一个 new 数组,包括所有原始元素和新元素。因此,在多次迭代的循环中,必须在每次迭代中创建一个新数组,这会导致非常差的性能。
This GitHub issue建议在将来进行潜在的增强,以允许以PowerShell惯用的方式构造固有可扩展的列表。
我也认为
[void]$RndNumberArr.Add($ran.Next(0,$max))
以防止Array.Add
输出比使用更快$RndNumberArr.Add($ran.Next(0,$max)) > $null
我说的对吗?
是的,使用表达式 [void]
的输出速度更快,尽管出于语法上的方便,您应该考虑使用同样快的$null = ...
,因为=
的运算符优先级最低,因此与(...)
不同,您无需担心将RHS包含在[void]
中,因为 cast 具有较高的优先级。
使用.NET方法有什么缺点吗?
首先让我们说明 上方 :
几乎可以调用任何.NET类型的方法是PowerShell的一项强大功能-每当PowerShell不通过其cmdlet /函数和运算符提供功能或没有为其提供足够性能时,.NET类型的方法通常会这样做。
也就是说,有 缺点:
在语法上,方法语法((...)
周围的参数列表中的,
)可能会与PowerShell的参数模式混淆(命令)语法(类似shell:在参数之间用{em> 隔开的(...)
周围没有空格); Set-StrictMode -Version 2
或更高版本可以帮助您检测无意间使用方法语法调用PowerShell cmdlet /函数的尝试。
虽然很少见,但由于PowerShell的 late-bound 性质,在更高版本的.NET Framework版本中引入的新方法重载有可能破坏现有代码 :如果新的重载碰巧导致现有代码绑定到它们,则事情可能会中断。
[System.Runtime.InteropServices.Marshal]::sizeof()
方法的新重载引入-请参见https://github.com/PowerShell/PowerShell/issues/3809#issuecomment-302804271 .NET类型方法的帮助未与PowerShell的帮助系统集成。
我的计算机硬件(特别是CPU)是否会影响PowerShell的执行速度,或者速度是否在某个时候受到限制?如果是这样,是否有办法增强分配的系统资源以提高速度?
我知道没有CPU的使用限制,但是我不能说是否/如何使用多个CPU /内核-如果有人知道,请告诉我们。
>通常来说,如果如果适合于给定任务,则 parallelization 可能会加快处理速度,并且有几种方法可以做到:
将{em>后台作业与Start-Job
作为一种更快的替代方法,使用 PowerShell SDK 为每个进程创建多个运行空间,这些由社区提供的PoshRSJob
module以打包好的PowerShell惯用格式提供
在Windows PowerShell中,工作流提供并行执行。
最后-同样, if 对于手头的任务来说是可行的-您可以使用Invoke-Command
将任务分散在多台计算机上,以并行执行。