当前位置:  开发笔记 > 开发工具 > 正文

需要更快地制作PowerShell脚本

如何解决《需要更快地制作PowerShell脚本》经验,为你挑选了1个好方法。

我教自己的Powershell所以我不知道它的一切.

我需要使用我输入的确切行数(数据库是预定义的)搜索数据库,它包含> 11800个条目.

你能帮我找一下这个慢的原因吗?

码:

$Dict = Get-Content "C:\Users\----\Desktop\Powershell Program\US.txt"

if($Right -ne "") {
    $Comb = $Letter + $Right
    $total = [int]0    
    $F = ""

    do {
        $F = $Dict | Select-Object -Index $total
        if($F.Length -eq $Num) {
            if($F.Chars("0") + $F.Chars("1") -eq $Comb) {
                Add-Content "C:\Users\----\Desktop\Powershell Program\Results.txt" "$F"
            }
        }
        $total++
        Write-Host $total
    } until([int]$total -gt [int]118619)

    $total = [int]0
    $F = ""
}

如何逐行搜索/匹配处理加快这一行?我是通过多线程做的吗?如果是这样的话?



1> briantist..:

看起来你在powershell之前至少已经知道了另一种语言,并且最初基本上复制了你在另一种语言中所做的事情.这是学习一门新语言的好方法,但当然在开始时你最终可能会遇到一些有点奇怪或无法表现的方法.

首先,我想分解您的代码实际执行的操作,作为一个粗略的概述:

    一次读取文件的每一行并将其存储在$Dict变量中.

    循环次数与行数相同.

    在循环的每次迭代中:

      获取与循环迭代匹配的单行(主要通过另一次迭代,而不是索引,稍后再详述).

      获取该行的第一个字符,然后获取第二个字符,然后将它们组合起来.

      如果它等于预定字符串,请将此行附加到文本文件.

步骤3-1是真正放慢这一点的原因

要了解原因,您需要了解PowerShell中的管道.接受和处理管道的Cmdlet会占用一个或多个对象,但它们一次处理一个对象.他们甚至无法访问管道的其余部分.

对于Select-Objectcmdlet 也是如此.因此,当您将一个包含18,500个对象的数组放入其中并将其输入时Select-Object -Index 18000,您需要发送17,999个对象进行检查/处理,然后才能为您提供所需的对象.您可以看到索引越大,所用时间越长越长.

既然你已经有了一个数组,你可以通过索引用方括号直接访问任何数组成员,[]如下所示:

$Dict[18000]

对于给定的数组,无论索引是什么,都需要相同的时间.

现在Select-Object -Index只要一个非常大的索引,你可能不会注意到需要多长时间.问题是你已经在整个数组中循环,所以这很复杂.

你基本上不必做总和1..18000大约是或大约162,000,000次迭代!(感谢user2460798纠正我的数学)

证明

我测试了这个.首先,我创建了一个包含19,000个对象的数组:

$a = 1..19000 | %{"zzzz~$_"}

然后我测量了两种访问它的方法.首先,用select -index:

measure-command { 1..19000 | % { $a | select -Index ($_-1 ) } | out-null }

结果:

TotalMinutes      : 20.4383861316667
TotalMilliseconds : 1226303.1679

然后使用索引operator([]):

measure-command { 1..19000 | % { $a[$_-1] } | out-null }

结果:

TotalMinutes      : 0.00788774666666667
TotalMilliseconds : 473.2648

结果非常引人注目,使用时间要长近2,600倍Select-Object.

计数循环

以上是导致您大幅放缓的唯一因素,但我想指出其他一些事情.

通常在大多数语言中,您将使用for循环来计数.在PowerShell中,这将是这样的:

for ($i = 0; $i -lt $total ; $i++) {
    # $i has the value of the iteration
}

简而言之,for循环中有三个语句.第一个是在循环开始之前运行的表达式.$i = 0将迭代器初始化为0,这是第一个语句的典型用法.

接下来是有条件的; 这将在每次迭代时进行测试,如果返回true,循环将继续.这里$i -lt $total比较检查,看$i是否小于$total其他地方定义的其他变量的值,可能是最大值.

最后一个语句在循环的每次迭代中执行.$i++与此相同$i = $i + 1在这种情况下,我们$i在每次迭代时递增.

它比使用do/ untilloop 更简洁,并且更容易理解,因为for循环的含义是众所周知的.

其他说明

如果您有兴趣了解更多的反馈工作你写的代码,看看代码审查.在发布之前请仔细阅读那里的规则.


这不是答案,而是一本书!^^做得好,再次
很好的答案,用`Measure-Command`来举例说明影响的道具!请注意,尽管管道性能损失适用于`| 同样是Out-Null,会稍微污染测量结果。请参阅我的[`Test-NullPerformance`](https://gist.github.com/IISResetMe/610deb873a96f331039d)脚本以供参考
@briantist很好地分析了这个问题.小尼:做18000!任何东西的迭代,即使你每皮秒一次,也需要比宇宙的年龄更长的时间(10 ^ 12*60*60*24*365.25*15*10 ^ 9,大约5*10 ^ 30皮秒).代表性的计算是_sum_为1..18000,大约是18000 ^ 2/2 = 162,000,000.
推荐阅读
落单鸟人
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有