让你的PowerShell For循环提速四倍 3


PowerShell性能优化系列文章

  1. PowerShell优化和性能测试
  2. 让你的PowerShell For循环提速四倍
  3. 优化PowerShell的性能和内存消耗
  4. PowerShell提速和多线程
  5. 优化PowerShell脚本的几个小技巧
  6. 轻量级的PowerShell性能测试

 

循环遍历信息是一个很基本的任务,每天估计在电脑上被很多人,以很多方式使用过很多次。在PowerShell中我们挑For循环来进行循环测试(见慢速循环)。

有一个性能问题潜藏在这个简单的例子中,当循环10000次以后,需要的时间可能超过两秒钟,而不是亚秒级别。但是当你敲击了回车键后,稍微有点不同,提示会像计数器一样,1000,2000这样数下去。

慢速循环

$range = 1..100000            
            
For($i=0; $i -lt $range.Count; $i++) {            
    $i            
}

一行之变

如果你要把这样的循环连续运行5次,你可以让整个脚本提速,甚至比运行一次循环还要快。只需要把数组的个数存储(缓存)到一个变量中,然后在For循环中使用它。

4倍提速

$range = 1..100000            
            
$count = $range.Count            
For($i=0; $i -lt $count; $i++) {            
    $i            
}

良好的习惯

把这当成一种习惯,是一个很好的习惯。它可以减少浪费,当你最不希望的大量数据丢过来时,能让你的脚本运行地更加快速。

更多结果

Test                Range TotalSeconds
----                ----- ------------
Test-WithoutCache      10     0.179358
Test-WithCache         10     0.065614
Test-WithoutCache     100     0.001333
Test-WithCache        100     0.001164
Test-WithoutCache    1000     0.006386
Test-WithCache       1000     0.005286
Test-WithoutCache   10000     0.178004
Test-WithCache      10000     0.055632
Test-WithoutCache  100000     0.246541
Test-WithCache     100000     0.041954
Test-WithoutCache 1000000     1.249059
Test-WithCache    1000000     0.591041

测试工具

执行测试并阅读脚本。注意怎样使用自定义的函数ql来存储数组,使用这个工具来处理更多的或者不同范围的测试非常方便。

一旦创建了PSobject属性TotalSeconds后,每一个测试会被执行,被计时,被格式化,并且被转换。

$TotalSeconds = [Double]("{0:#0.#####0}" -f            
    (Measure-Command { & $test (1..$range) }).TotalSeconds)

 

Function Test-WithoutCache ($data) {            

    $sum = 0            
    # antipattern            
    # access the array count on each iteration            
    for($idx = 0 ; $idx -lt $data.count; $idx++) {            
        $sum+=$data[$idx]            
    }                
    $sum            
}            
            
Function Test-WithCache ($data) {            
    # capture the count; cache it            
    $count = $data.count            
    $sum = 0            
    # use the $count variable in the            
    # for loop and improve performance 4x            
    for($idx = 0 ; $idx -lt $count; $idx++) {            
        $sum+=$data[$idx]            
    }                
    $sum            
}            
            
function ql {$args}            
            
$tests  = ql Test-WithoutCache Test-WithCache            
$ranges = ql 10 100 1000 10000 100000 1000000            
            
$(ForEach($range in $ranges) {            
    ForEach($test in $tests) {            
        $msg = ("[{0}] Running {1} with {2} items" -f  (Get-Date), $test, $range)            
        Write-Host -ForegroundColor Green $msg            
        New-Object PSObject -Property @{            
            TotalSeconds = [Double]("{0:#0.#####0}" -f (Measure-Command { & $test (1..$range) }).TotalSeconds)            
            Range  = $range            
            Test   = $test            
        } | Select Test, Range, TotalSeconds            
    }            
}) | Format-Table -AutoSize

原文作者:DOUG FINKE
原文链接Make Your PowerShell For Loops 4x Faster

本文链接: https://www.pstips.net/make-your-powershell-for-loops-4x-faster.html
请尊重原作者和编辑的辛勤劳动,欢迎转载,并注明出处!

关于 Mooser Lee

我是一个Powershell的爱好者,创建了PowerShell中文博客,热衷于Powershell技术的搜集和分享。本站部分内容来源于互联网,不足之处敬请谅解,并欢迎您批评指正。

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

3 条评论 “让你的PowerShell For循环提速四倍

  • 我用10000做测试,循环下来的结果是一样的
    64bit机器

    第一种
    $range = 1..10000
    get-date > result.txt
    For($i=0; $i -lt $range.Count; $i++) {
    $i >>result.txt
    }
    get-date >>result.txt
    结果:
    Friday, October 14, 2016 2:19:11 PM

    Friday, October 14, 2016 2:20:21 PM

    第二种
    $range = 1..10000
    get-date > result.txt
    $count = $range.Count
    For($i=0; $i -lt $count; $i++) {
    $i >>result.txt
    }
    get-date >>result.txt

    结果:
    Friday, October 14, 2016 2:17:26 PM
    Friday, October 14, 2016 2:18:36 PM

    两次都是70s,求解呀

    • 凯旋

      其实提升并不明显,时间都被写文件和输出占用了。把循环体中的写文件删掉,循环次数改成300万次,提升就能看出来了。