我有一个关于 powershell (v4) 的新手问题。
给定以下代码,
- 当我在循环中执行 $t = $i 时需要 0.5 秒
- 当我在循环中执行 $t = DoNothing($i) 时需要 11.5 秒
- 当我在循环中执行 $t = DoNothing $i 时需要 11.5 秒
如果我改变函数 DoNothing 的内容来做某事,时间不会延长太多。
显然我在某处犯了一个大错误,但我看不到它在哪里。非常感谢您帮助我理解我的错误。
function DoNothing($val)
{
return $val
}
Write-Host "Script started..."
$elapsed = [System.Diagnostics.Stopwatch]::StartNew()
for($i=1
$i -le 100000
$i++){
#$t = $i
#$t = DoNothing($i)
$t = DoNothing $i
}
Write-Host "Script complete."
Write-Host "Total Elapsed Time: $($elapsed.Elapsed.ToString())"
最佳答案
好问题。我相信这只是在 PowerShell 中进行函数调用的性能开销,但我做了一些实验来检查。
我注意到的一些事情:
1) 与仅在不保存文件的情况下使用 PowerShell ISE 相比,保存文件可将性能提高约 75%(从 7.3 秒增加到 4.3 秒)。
2) 将 DoNothing
转换为无参数函数可将执行时间额外缩短约 25%(从 4.3 秒缩短至 3.3 秒)。如果将 $i
创建为全局变量可以节省时间,那么这将很有用,但我也对其进行了测试,遗憾的是,它将执行时间增加到 4.7 秒。
3) 我认为也许明确请求将 $val
作为 int 传递会减少执行时间,但事实并非如此。时间增加了大约 0.2 秒。
4) 在调用 DoNothing
时命名 -val
参数 ($t = DoNothing -val $i
) 没有提高性能。
5) 使用 $val
而不是 return $val
没有提高性能。
6) 使用 -lt
而不是 -le
并没有提高性能。
7) 将 DoNothing
添加到只有 DoNothing
函数的 PS 模块会严重降低性能(从 4.3 秒到 15 秒) .
所以,我认为这都是由于函数开销造成的。我在您的代码中没有看到任何“错误”。
这是一个有趣的实验,当我将来选择使用 PowerShell 函数时可能会改变。我想知道这与其他脚本语言相比如何。
出于好奇,我使用 C# 运行了这些相同的操作,整个过程在千分之一秒内完成。代码如下。
class Program
{
private static int DoNothing(int val) {
return val;
}
static void Main(string[] args)
{
System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew();
for (int i = 1; i <= 100000; i++)
{
int t = DoNothing(i);
}
Console.WriteLine(watch.Elapsed.ToString());
Console.ReadKey();
}
}
现在我比这更进一步了。我认为如果您真的需要它更快,也许您可以将工作负载从 PowerShell 转移到 C#。这最终比 PowerShell 中的初始实现快得多,但比仅 C# 选项慢。 此代码运行时间约为 0.03 秒。请参阅下面的代码。
PowerShell(调用 C#)
$elapsed = [System.Diagnostics.Stopwatch]::StartNew()
Write-Host "Script started..."
$lib = [Reflection.Assembly]::LoadFile("C:\Users\you\source\ClassLibrary1\bin\Debug\ClassLibrary1.dll")
$type = $lib.GetType("ClassLibrary1.Class1")
$method = $type.GetMethod("MyFunction")
$o = [Activator]::CreateInstance($type)
$method.Invoke($o, $null)
Write-Host "Script complete."
Write-Host "Total Elapsed Time: $($elapsed.Elapsed.ToString())"
C#(完成工作)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ClassLibrary1
{
public class Class1
{
public static int DoNothing(int val)
{
return val;
}
public static void MyFunction()
{
for (int i = 1; i <= 100000; i++)
{
int t = DoNothing(i);
}
}
}
}
关于powershell - 调用自定义函数非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49199261/