我正在阅读Windows PowerShell 3.0 Step by Step书籍以获得对PowerShell的更多见解。
在第201页,作者certificate了一个filter比function相同的函数更快。
他的电脑上这个脚本需要2.6秒钟:
MeasureAddOneFilter.ps1 Filter AddOne { "add one filter" $_ + 1 } Measure-Command { 1..50000 | addOne }
这一个4.6秒
MeasureAddOneFunction.ps1 Function AddOne { "Add One Function" While ($input.moveNext()) { $input.current + 1 } } Measure-Command { 1..50000 | addOne }
如果我运行这个代码是得到他的结果完全相反:
.\MeasureAddOneFilter.ps1 Days : 0 Hours : 0 Minutes : 0 Seconds : 0 Milliseconds : 226 Ticks : 2266171 TotalDays : 2,62288310185185E-06 TotalHours : 6,29491944444444E-05 TotalMinutes : 0,00377695166666667 TotalSeconds : 0,2266171 TotalMilliseconds : 226,6171 .\MeasureAddOneFunction.ps1 Days : 0 Hours : 0 Minutes : 0 Seconds : 0 Milliseconds : 93 Ticks : 933649 TotalDays : 1,08061226851852E-06 TotalHours : 2,59346944444444E-05 TotalMinutes : 0,00155608166666667 TotalSeconds : 0,0933649 TotalMilliseconds : 93,3649
谁可以给我解释一下这个?
除非提交人提供更多证据,否则他可能只是热气腾腾。 你已经运行了testing并得到了结果,并certificate他错了。
编辑:从Jeffrey Snover的博客:
filter是一个只有一个进程脚本块的函数
单靠这一点还不足以说服我,一个filter将会比一个function具有速度优势,因为它们都有相同的过程块。
那1950年代的装备又是什么样子的?
PS C:\Users\Ryan> Measure-Command { Filter AddOne { $_ + 1 }; AddOne 1 } TotalMilliseconds : 7.7266 PS C:\Users\Ryan> Measure-Command { Function AddOne { $_ + 1 }; AddOne 1 } TotalMilliseconds : 0.4108
4.6秒是重击。 也许作者在创build二进制文件之前使用了某种CTP版本的Powershell。 :P
最后,在新的Powershell会话中尝试您的testing,但以相反的顺序。 首先尝试function,然后尝试filter,反之亦然:
PS C:\Users\Ryan> Measure-Command { Function AddOne { $_ + 1 }; AddOne 1 } TotalMilliseconds : 6.597 PS C:\Users\Ryan> Measure-Command { Filter AddOne { $_ + 1 }; AddOne 1 } TotalMilliseconds : 0.4055
看到? 你跑的第一个总是比较慢。 这只是关于.NET内部已经加载了东西到内存中,使得第二个操作更快,无论是一个函数还是一个filter。
我会承认,尽pipe函数运行的次数似乎仍然比Filter要快。
Measure-Command { Function AddOne($Num) { Return $Num += 1 }; 1..50000 | AddOne $_ } TotalMilliseconds : 13.9813 Measure-Command { Filter AddOne($Num) { Return $Num += 1 }; 1..50000 | AddOne $_ } TotalMilliseconds : 69.5301
所以作者是错的…现在我不会因为之前从未使用Filter而不是使用Function而感到不快。
实际上,如果在两个testing中使用相同的$ _,则差异会小得多。 我没有调查原因,但我想这是因为作者在两个testing中都没有使用相同的方法。 另外,控制台输出可能会干扰结果。 如果你削减这些部分,数字是非常相似的。 看到:
Function AddOneFunction { process { $_ + 1 } } Filter AddOneFilter { $_ + 1 } write-host "First" Measure-Command { 1..50000 | AddOneFilter } | select totalMilliseconds Measure-Command { 1..50000 | AddOneFilter } | select totalMilliseconds Measure-Command { 1..50000 | AddOneFilter } | select totalMilliseconds Measure-Command { 1..50000 | AddOneFilter } | select totalMilliseconds Measure-Command { 1..50000 | AddOneFilter } | select totalMilliseconds write-host "Second" Measure-Command { 1..50000 | AddOneFunction } | select totalMilliseconds Measure-Command { 1..50000 | AddOneFunction } | select totalMilliseconds Measure-Command { 1..50000 | AddOneFunction } | select totalMilliseconds Measure-Command { 1..50000 | AddOneFunction } | select totalMilliseconds Measure-Command { 1..50000 | AddOneFunction } | select totalMilliseconds
即使您更改命令的顺序,结果也将非常接近。
First TotalMilliseconds ----------------- 84.6742 84.7646 89.8603 82.3399 83.8195 Second 86.8978 87.4064 89.304 94.4334 87.0135
该文档还说,filter基本上是只有过程块function的快捷方式。 函数,除非指定了一个进程块(或其他一些像使用自动variables如$ input这样的技术),否则运行一次,不要使用input,也不要传递给pipe道中的下一个命令。