gpt4 book ai didi

c# - 谁能帮我解释一下这些方法的时间安排?

转载 作者:行者123 更新时间:2023-11-30 15:47:46 25 4
gpt4 key购买 nike

此代码对两个方法(MyMethod1MyMethod2)调用 n 次进行计时,但使用不同的属性( MyAspect1, MyAspect2).

MyAspect1 除了让 MyMethod1 运行 (Proceed()) 之外不包含任何逻辑。

MyAspect2MyMethod2 做同样的事情,但也创建了一个任务,提供一个匿名委托(delegate)来运行,这意味着 CPU 的工作量接近于零(修剪字符串)。

我希望 MyMethod1MyMethod2 的迭代时间大致相同。

实际时间如下;它们似乎违反直觉,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 MethodInterceptionAspect

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

最佳答案

好吧,首先我会尝试确定这是否与 PostSharp 有任何关系。我会尝试在不涉及任何 AOP 的情况下调用相同的方法。

不过这是我的怀疑:

  • 25000 个滴答声(请注意,时间很短)是由于 PostSharp 基础设施的 JIT 位。因此,它们是固定成本,不必通过第二种方法再次支付。您可以通过切换测试顺序来验证这一点。然而,鉴于这些数字,我怀疑设置任务工厂等会产生另一个恒定成本...这可以解释为什么方法 2 的 100 次迭代不会比 5 次迭代花费更长的时间。 p>

  • 创建任务不是免费的,我也不希望它是免费的。只是您正在创建一个对象这一事实就意味着工作正在进行……然后是跨任务和线程的调度和协调。并行扩展很好,但它不能创造奇迹。我不知道 PFX 将如何分散工作,但有可能生成的一些额外工作(任务很短,但仍然必须执行)最终与主线程在同一个核心上。您正在非常快速地创建大量任务。

  • 这两种方法之间的差异可能足以改变它们是否可以内联。由于使用 PostSharp,这在某种程度上被混淆了,但如果发现情况确实如此,我不会感到完全惊讶。

  • 在方法 2 的情况下,缩放不是完全线性的,但也相差不远。如果你采用 6000 + 23 * N 的公式作为一个快速而粗略的近似值,您会期望 6115、8300、29000、236000 和 23006000 的值 - 非常相差不远。

  • 我强烈怀疑上次测试中第一个方法的巨大数字是由于垃圾回收和堆增长造成的。您在这里创建了大量对象,我怀疑它正在执行完整的 GC 并适本地扩展各个代 - 同一测试中的方法 2 然后利用了更大的堆。

这些实际上只是猜测,但它们为您所看到的一切提供了某种解释:)

关于c# - 谁能帮我解释一下这些方法的时间安排?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3224068/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com