标题: [技术讨论] PowerShell脚本块的递归性能检验 [打印本页]
作者: Nsqs 时间: 2023-10-15 18:41 标题: PowerShell脚本块的递归性能检验
本帖最后由 Nsqs 于 2023-10-21 06:51 编辑
第一段 用scriptblock测试- using namespace System.Collections
- using namespace System.Collections.Generic
- using namespace System.Diagnostics
- [Stopwatch]$sw=@{}
- [List[int]]$ll=@{}
- function m($a){
- [List[int]]$l=@{}
- [scriptblock]$fn={param($x)$l.Add($x);if($x -eq 1){return $l}else{$x--}$fn.Invoke($x)}
- $fn.Invoke($a)
- }
- function fn($x){$ll.Add($x);if($x -eq 1){return $ll}else{$x--}fn $x}
- $sw.Start()
- $a=1..1000|%{$x=m 10}
- $t=$sw.Elapsed.TotalSeconds.ToString('0.00s')
- $ll.Clear()
- $sw.Restart()
- $b=1..1000|%{$x=fn 10}
- $t;$sw.Elapsed.TotalSeconds.ToString('0.00s')
- $sw.Stop()
复制代码
第二段 用func测试- using namespace System.Collections
- using namespace System.Collections.Generic
- using namespace System.Diagnostics
- [Stopwatch]$sw=@{}
- [List[int]]$ll=@{}
- function m($a){
- [List[int]]$l=@{}
- [func[int,IList]]$fn={param($x)$l.Add($x);if($x -eq 1){return $l}else{$x--}$fn.Invoke($x)}
- $fn.Invoke($a)
- }
- function fn($x){$ll.Add($x);if($x -eq 1){return $ll}else{$x--}fn $x}
- $sw.Start()
- $a=1..1000|%{$x=m 10}
- $t=$sw.Elapsed.TotalSeconds.ToString('0.00s')
- $ll.Clear()
- $sw.Restart()
- $b=1..1000|%{$x=fn 10}
- $t;$sw.Elapsed.TotalSeconds.ToString('0.00s')
- $sw.Stop()
复制代码
第三段 用action测试- using namespace System.Collections
- using namespace System.Collections.Generic
- using namespace System.Diagnostics
- [Stopwatch]$sw=@{}
- [List[int]]$ll=@{}
- function m($a){
- [List[int]]$l=@{}
- [scriptblock]$fn={param($x)$l.Add($x);if($x -eq 1){$global:res=$l;return}else{$x--}$fn.Invoke($x)}
- $fn.Invoke($a)
- }
- function fn($x){$ll.Add($x);if($x -eq 1){return $ll}else{$x--}fn $x}
- $sw.Start()
- $a=1..1000|%{m 10;$x=$res}
- $t=$sw.Elapsed.TotalSeconds.ToString('0.00s')
- $ll.Clear()
- $sw.Restart()
- $b=1..1000|%{$x=fn 10}
- $t;$sw.Elapsed.TotalSeconds.ToString('0.00s')
- $sw.Stop()
复制代码
结果就不公布了,每台电脑计算力不一样,自己去体会
可以肯定一点的是性能这一块function,只能算是个中庸吧,玩递归的话,还是慎重考虑
作者: Nsqs 时间: 2023-10-15 18:45
忘记说了是在5.1下测试的,懒得再弄了,休息,如果有人用高版本测试结果发现速度更快的话,可以说一声,欢迎共同学习和进步
作者: yyz219 时间: 2023-10-15 19:49
谢谢分享了
作者: Nsqs 时间: 2023-10-21 07:00
本帖最后由 Nsqs 于 2023-10-21 07:49 编辑
重新修改了一下,感觉这样对比更加有说服力一点了
第一轮对比scriptblock与function
0.36s
1.18s
第二轮func与function
1.18s
1.16s
第三轮action与function
0.34s
1.19s
func委托函数套在函数里与直接用func委托的测试:- using namespace System.Collections
- using namespace System.Collections.Generic
- using namespace System.Diagnostics
- function func($a){
- [List[int]]$l=@{}
- [func[int,IList]]$fn={param($x)$l.Add($x);if($x -eq 1){return $l}else{$x--}$fn.Invoke($x)}
- $fn.Invoke($a)
- }
- [List[int]]$la=@{}
- [func[int,ilist]]$fn={param($x)$la.Add($x);if($x -eq 1){return $l}else{$x--}$fn.Invoke($x)}
- [Stopwatch]$sw=@{}
- $sw.Start()
- 1..1000|%{$x=func 10}
- $t=$sw.Elapsed.TotalSeconds.ToString('0.00s')
- $sw.Restart()
- 1..1000|%{$la=@{};$r=$fn.Invoke(10)}
- $t;$sw.Elapsed.TotalSeconds.ToString('0.00s')
- $sw.Stop()
复制代码
运行结果:
1.16s
0.32s
也就是说如果你想写递归的话,性能方面写直接单写一个function和function+func是一样的如果在function里再写func
既然速度是一样的就不如直接写func来的快
想偷懒又想在function里写函数用 $scriptblock=#{脚本块} 能节省一些代码量,可以不用声明
这是AI的回答:
在 PowerShell 中,闭包是指一个函数可以访问在其定义之外定义的变量。当您在函数内部调用 func 时,
每次调用都会创建一个新的闭包对象,该闭包对象包含了函数定义时所捕获的变量。这样会导致每次调用 func 时都需要创建新的闭包对象。
根据AI的回答,大概是因为scriptblock是PowerShell独有的方法
套在函数内不需要额外创建新的委托因此function里写func委托函数每次调用 function 都会重新创建一个委托函数
scriptblock则不用..所以直接调用$fn.Invoke()效率会比套在function里的$fn速度更快
我这个测试结果是在ise内测试的,如果双击运行脚本速度只能更快
作者: Nsqs 时间: 2023-10-21 07:51
本帖最后由 Nsqs 于 2023-10-21 07:56 编辑
测试一下套在function里的scriptblock与直接调用scriptblock的递归测试- using namespace System.Collections
- using namespace System.Collections.Generic
- using namespace System.Diagnostics
- function func($a){
- [List[int]]$l=@{}
- [scriptblock]$fn={param($x)$l.Add($x);if($x -eq 1){return $l}else{$x--}$fn.Invoke($x)}
- $fn.Invoke($a)
- }
- [List[int]]$lc=@{}
- [scriptblock]$fn={param($x)$lc.Add($x);if($x -eq 1){return $l}else{$x--}$fn.Invoke($x)}
- [Stopwatch]$sw=@{}
- $sw.Start()
- 1..1000|%{$x=func 10}
- $t=$sw.Elapsed.TotalSeconds.ToString('0.00s')
- $sw.Restart()
- 1..1000|%{$la=@{};$r=$fn.Invoke(10)}
- $t;$sw.Elapsed.TotalSeconds.ToString('0.00s')
- $sw.Stop()
复制代码
运行结果:
0.36s
0.28s
这两速度基本可以忽略不计
递归性能最差的应当就是直接用function了感觉
作者: wanghan519 时间: 2023-10-21 11:29
回复 5# Nsqs
感谢分享
还有就是递归的深度影响很大,10层看不出来,100,200,1000层的耗时不是线性增加的
作者: Nsqs 时间: 2023-10-21 11:44
本帖最后由 Nsqs 于 2023-10-21 11:48 编辑
回复 6# wanghan519
结合自己情况来用吧,这个测试至少证明写递归直接在函数里定义scriptblock是最方便的,不需要提前声明泛类型委托函数
如果直接使用PowerShell自带的Function去写递归性能就不怎么样
欢迎光临 批处理之家 (http://bathome.net./) |
Powered by Discuz! 7.2 |