PowerShell执行速度的提高

时间:2018-08-25 08:19:03

标签: arrays performance powershell arraylist

昨晚我玩了一些用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的执行速度,或者速度是否在某个时候受到限制?如果是这样,是否有办法增强分配的系统资源以提高速度?

非常感谢。

2 个答案:

答案 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语法foreach1..$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版本中引入的新方法重载有可能破坏现有代码 :如果新的重载碰巧导致现有代码绑定到它们,则事情可能会中断。

  • .NET类型方法的帮助未与PowerShell的帮助系统集成


  

我的计算机硬件(特别是CPU)是否会影响PowerShell的执行速度,或者速度是否在某个时候受到限制?如果是这样,是否有办法增强分配的系统资源以提高速度?

我知道没有CPU的使用限制,但是我不能说是否/如何使用多个CPU /内核-如果有人知道,请告诉我们。

>

通常来说,如果如果适合于给定任务,则 parallelization 可能会加快处理速度,并且有几种方法可以做到:

  • 将{em>后台作业与Start-Job

  • 作为一种更快的替代方法,使用 PowerShell SDK 为每个进程创建多个运行空间,这些由社区提供的PoshRSJob module以打包好的PowerShell惯用格式提供

  • 在Windows PowerShell中,工作流提供并行执行。

  • 最后-同样, if 对于手头的任务来说是可行的-您可以使用Invoke-Command将任务分散在多台计算机上,以并行执行。