C# 使循环中的第一次迭代与其他迭代的速度相同

C# 使循环中的第一次迭代与其他迭代的速度相同,c#,C#,我正在尝试对一些东西进行基准测试 我有一个像 for (int i = 1; i <= 1000; i++) { Thing thing = createThing(i); DateTime startTime = DateTime.Now; thing.ComputationallyExpensiveOp(); TimeSpan elapsed = DateTime.Now - startTime; Console.WriteLine(Stri

我正在尝试对一些东西进行基准测试

我有一个像

for (int i = 1; i <= 1000; i++)
{
    Thing thing = createThing(i);

    DateTime startTime = DateTime.Now;
    thing.ComputationallyExpensiveOp();
    TimeSpan elapsed = DateTime.Now - startTime;

    Console.WriteLine(String.Format("i = " + i + "\ttime = " + elapsed.TotalMilliseconds);
}
几十年来,我一直在使用这种循环。我从未经历过,这样的for循环是第一次迭代中延迟的原因

我对你的东西的实现一无所知,但我很确定你拖延的原因就在那里。不在循环中。

将整个循环体复制到外部为我修复了它

Thing thing = createThing(1);

DateTime startTime = DateTime.Now;
thing.ComputationallyExpensiveOp();
TimeSpan elapsed = DateTime.Now - startTime;

Console.WriteLine(String.Format("i = " + 1 + "\ttime = " + elapsed.TotalMilliseconds);

for (int i = 1; i <= 1000; i++)
{
    thing = createThing(i);

    startTime = DateTime.Now;
    thing.ComputationallyExpensiveOp();
    elapsed = DateTime.Now - startTime;

    Console.WriteLine(String.Format("i = " + i + "\ttime = " + elapsed.TotalMilliseconds);
}

我不太确定原因,但现在第一次迭代的运行时更像预期的运行时。

您尝试了哪种预热初始化,但没有成功?通常调用要进行基准测试的代码work@harold我编辑以显示。我将要测试复制Conole.WriteLine和计时等,可能只是时间x循环,并打印批次的中值或平均值。既然听起来你无法控制CreateThing中的缓存,那么我们如何在不知道CreateThing和ComputeAllyExpensiveOp中发生了什么的情况下合理地回答这个问题?这两种方法中存在什么缓存?我复制了循环上方的整个循环体,它似乎已经修复了它。Ofc我不能确定,但现在的数字看起来更像预期的。我很高兴这个解决方案对您有效。然而,这仍然是一个奇怪的问题。在for循环之外声明这三个变量不应导致明显的性能提高,尤其是当thing.ComputationallyExpensiveOp调用将消耗逻辑的大部分总处理能力时。如果你有机会,我建议你进一步调查这个问题。如果这个问题的真正根源仍未被发现,你可能会发现你自己迟早会遇到它的自然再现。到那时可能更难确定和解决。@BartHofland是的,我也认为这很奇怪,幸运的是,这不是我将来将重用的任何东西的一部分,但我可能会在几天后再次调查,以更新此帖子,所以可能两者都不是,但是在C中,第一次调用任何方法的速度都很慢,因为代码还没有进行JIT编译,所以JIT的时间包括在基准测试中,如果您调用cold codeTrue,但是除非OP中的ComputeAllyExpensiveOp在计算上不是很昂贵,JIT编译并不能解释循环中第一次迭代的执行时间延长了几个数量级。。。我知道JIT编译有开销,但正如我已经说过的,在我的整个职业生涯中,我从未经历过由编译器/环境造成的这种延迟。它总是主要与我开发的逻辑的实现细节有关。
Thing thing = createThing(1);

DateTime startTime = DateTime.Now;
thing.ComputationallyExpensiveOp();
TimeSpan elapsed = DateTime.Now - startTime;

Console.WriteLine(String.Format("i = " + 1 + "\ttime = " + elapsed.TotalMilliseconds);

for (int i = 1; i <= 1000; i++)
{
    thing = createThing(i);

    startTime = DateTime.Now;
    thing.ComputationallyExpensiveOp();
    elapsed = DateTime.Now - startTime;

    Console.WriteLine(String.Format("i = " + i + "\ttime = " + elapsed.TotalMilliseconds);
}