为什么表达式本身在方法参数中的存在使方法在 C# 中变慢
Why the pressence of Expression itself among method parameters makes method slow in C#
请考虑方法:
private void FastMethod(string param)
{
}
private void SlowMethod<T>(Expression<Func<T>> expression)
{
}
以及以下测试:
[TestMethod]
public void Test()
{
var stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < 1000000; i++)
{
this.FastMethod("TestContext");
}
TestContext.WriteLine("Fast time: " + stopwatch.ElapsedMilliseconds);
stopwatch.Restart();
for (int i = 0; i < 1000000; i++)
{
this.SlowMethod(() => this.TestContext);
}
TestContext.WriteLine("Slow time: " + stopwatch.ElapsedMilliseconds);
}
输出为:
Fast time: 4
Slow time: 2249
http://i.imgur.com/eYcBfZX.png
我知道这是每 100 万次调用,所以这看起来不像是严重的性能问题。
但我想在 属性 setter 中有一些基于表达式的逻辑,它们将被相当频繁地调用 + 我只是好奇。
这里有space优化吗? (我无法摆脱方法参数中的Expression
,基本上我需要做一些语法树解析。有趣的是解析本身足够快)。
因为 C# 编译器会为调用方法的每次迭代生成表达式树。它不是免费的。
如果您查看已编译的 IL——您可以看到 scenes.There 背后的内容,其中涉及大量分配。
您可以通过在循环外初始化表达式树来确认这一点。
Expression<Func<TestContext>> parameter = () => this.TestContext;
for (int i = 0; i < 1000000; i++)
{
this.SlowMethod(parameter);
}
这输出:
Fast time: 3
Slow time: 3
请考虑方法:
private void FastMethod(string param)
{
}
private void SlowMethod<T>(Expression<Func<T>> expression)
{
}
以及以下测试:
[TestMethod]
public void Test()
{
var stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < 1000000; i++)
{
this.FastMethod("TestContext");
}
TestContext.WriteLine("Fast time: " + stopwatch.ElapsedMilliseconds);
stopwatch.Restart();
for (int i = 0; i < 1000000; i++)
{
this.SlowMethod(() => this.TestContext);
}
TestContext.WriteLine("Slow time: " + stopwatch.ElapsedMilliseconds);
}
输出为:
Fast time: 4
Slow time: 2249
http://i.imgur.com/eYcBfZX.png
我知道这是每 100 万次调用,所以这看起来不像是严重的性能问题。
但我想在 属性 setter 中有一些基于表达式的逻辑,它们将被相当频繁地调用 + 我只是好奇。
这里有space优化吗? (我无法摆脱方法参数中的Expression
,基本上我需要做一些语法树解析。有趣的是解析本身足够快)。
因为 C# 编译器会为调用方法的每次迭代生成表达式树。它不是免费的。
如果您查看已编译的 IL——您可以看到 scenes.There 背后的内容,其中涉及大量分配。
您可以通过在循环外初始化表达式树来确认这一点。
Expression<Func<TestContext>> parameter = () => this.TestContext;
for (int i = 0; i < 1000000; i++)
{
this.SlowMethod(parameter);
}
这输出:
Fast time: 3
Slow time: 3