小编典典

在C#中对小型代码样本进行基准测试,是否可以改善此实现?

c#

经常在SO上我发现自己对一小段代码进行基准测试,以了解哪种实现速度最快。

我经常看到这样的评论,即基准测试代码未考虑到jitting或垃圾收集器。

我具有以下逐渐发展的简单基准测试功能:

  static void Profile(string description, int iterations, Action func) {
        // warm up 
        func();
        // clean up
        GC.Collect();

        var watch = new Stopwatch();
        watch.Start();
        for (int i = 0; i < iterations; i++) {
            func();
        }
        watch.Stop();
        Console.Write(description);
        Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds);
    }

用法:

Profile("a descriptions", how_many_iterations_to_run, () =>
{
   // ... code being profiled
});

此实现有任何缺陷吗?是否足以证明实现X在Z迭代上比实现Y快?您能想到任何改善此方法的方法吗?

编辑 显然,基于时间的方法(而不是迭代)是首选,有人在时间检查不会影响性能的情况下实现吗?


阅读 294

收藏
2020-05-19

共1个答案

小编典典

这是修改后的功能:根据社区的建议,随时对其进行修订,使其成为社区Wiki。

static double Profile(string description, int iterations, Action func) {
    //Run at highest priority to minimize fluctuations caused by other processes/threads
    Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
    Thread.CurrentThread.Priority = ThreadPriority.Highest;

    // warm up 
    func();

    var watch = new Stopwatch();

    // clean up
    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();

    watch.Start();
    for (int i = 0; i < iterations; i++) {
        func();
    }
    watch.Stop();
    Console.Write(description);
    Console.WriteLine(" Time Elapsed {0} ms", watch.Elapsed.TotalMilliseconds);
    return watch.Elapsed.TotalMilliseconds;
}

确保 在启用优化的情况下在Release中进行编译,并在Visual Studio外部运行测试
。最后一部分很重要,因为即使在发布模式下,JIT也会通过附加的调试器来限制其优化。

2020-05-19