【发布时间】:2010-07-11 17:55:02
【问题描述】:
此代码对两种方法的 n 调用进行计时,这两种方法均不执行任何操作(MyMethod1、MyMethod2)但使用不同的属性(MyAspect1、MyAspect2)进行装饰。
MyAspect1 除了让MyMethod1 运行(Proceed())之外,不包含任何逻辑。
MyAspect2 对MyMethod2 执行相同操作,但还会创建一个任务,提供一个匿名委托来运行,这意味着 CPU 的工作量接近于零(修剪字符串)。
我希望 MyMethod1 和 MyMethod2 上的迭代时间大致相同。
实际时间如下;它们似乎与直觉相悖,MyMethod1 开始时明显较慢(与我的预期相反),最终从 10000 次迭代开始显着输掉比赛。谁能帮我解释一下?
Test results (average of 3 runs per iteration value):
No. of iterations | Ticks
Method 1 | Method 2
5 25282 6999
100 22128 8176
1000 22982 23720
10000 25995 265621
1000000 994359 25125076
---------------------------------------------------
public class TestClass2
{
public void MyTest()
{
const int iterations = 100;
var stopWatch = new Stopwatch();
stopWatch.Start();
for (int x = 0; x < iterations; x++)
{
MyMethod1();
}
stopWatch.Stop();
Console.WriteLine("Method1 calls duration: " + stopWatch.ElapsedTicks);
stopWatch.Reset();
stopWatch.Start();
for (int x = 0; x < iterations; x++)
{
MyMethod2();
}
stopWatch.Stop();
Console.WriteLine("Method2 calls duration: " + stopWatch.ElapsedTicks);
}
[MyAspect1]
private void MyMethod1() {}
[MyAspect2]
private void MyMethod2() {}
}
[Serializable]
public class MyAspect1 : AsynchronousMetricsAspect
{
public override void OnInvoke(MethodInterceptionArgs args)
{
args.Proceed();
}
}
//NOTE: this type is the same as MyAspect1, but adds a Task creation
[Serializable]
public class MyAspect2 : AsynchronousMetricsAspect
{
public override void OnInvoke(MethodInterceptionArgs args)
{
args.Proceed();
Task.Factory.StartNew(() => "bleh".Trim()); //invoke the logging method asynchronously
}
}
更多信息:正在从 ReSharper NUnit VS 插件调用测试,属性为 PostSharp MethodInterceptionAspects。
Edit: Updated figures for when the methods are pre-invoked before the tests, to ensure any JIT compilation has occurred.
Test results (ballpark):
No. of iterations | Ticks
Method 1 | Method 2
5 22 437
100 37 2204
1000 192 24476
10000 7931 286403
100000 115451 2862439
1000000 695950 29049021
10000000 8347867 275777590
【问题讨论】:
-
您能否在分析器(nProf、EQATEC 等)中调用测试?
-
我已经下载了dot trace,当我弄清楚如何使用它时会报告我的发现。
-
查看 PostSharp 使用 Reflector 生成了哪些代码。
-
好的,我已经对这个感兴趣了。 J Skeet 对 PostSharp 基础设施的 JIT 处理是正确的——预运行代码,从结果中移除了大部分“固定”成本。将属性代码从 PostSharp 属性中移出对 Method1 产生了重大影响 - 怀疑那里正在进行严重的编译器优化。这样做改进了 Method2,但不是按 mag 的顺序。这个实验只是为了展示影响性能的众多因素。代码 - 决定某事是否高性能并不简单。
标签: c# performance