如何可靠地度量c#中的代码效率/复杂性/性能/昂贵性

本文关键字:复杂性 效率 性能 代码 何可 度量 | 更新日期: 2023-09-27 18:17:07

我的问题由两部分组成:

  1. 在c#中,除了使用定时器(如Stopwatch)之外,还有什么好的方法来测量计算工作量吗?下面是我一直在做的,但是粒度不是很大,每次返回的结果都不一样。我想知道是否有更精确的度量,例如CPU操作计数,以便返回的结果可以一致。

            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
            //do work
            stopWatch.Stop();
            TimeSpan ts = stopWatch.Elapsed;
            Console.WriteLine(ts);
    
  2. 如果1中的替代方法不可能,我如何使性能测试结果的变量更小?有哪些因素可以使结果发生变化?关闭所有其他正在运行的应用程序会有帮助吗?(我确实试过,但似乎没有明显的效果。)在虚拟机、沙箱等上运行测试怎么样?

(在输入前面的文本之后,我意识到我也尝试了Visual Studio自带的性能分析功能。由于抽样方法的原因,测试结果显得比较粗糙。所以我也要排除这个选项)

如何可靠地度量c#中的代码效率/复杂性/性能/昂贵性

您需要获得一个分析工具。但是,如果您在循环中多次运行测试,并且仅在垃圾收集生成保持不变的情况下获取测试结果,则可以更可靠地使用StopWatch

:

var timespans = new List<TimeSpan>();
while (true)
{
    var count = GC.CollectionCount(0);
    var sw = Stopwatch.StartNew();
    /* run test here */
    sw.Stop();
    if (count == GC.CollectionCount(0))
    {
        timespans.Add(sw.Elapsed);
    }
    if (timespans.Count == 100)
    {
        break;
    }
}

这将给您100个没有发生垃圾收集的测试。那么从平均值开始算就很好了。

如果您发现您的测试从来没有在不调用垃圾收集的情况下运行,那么请尝试计算被触发的GC的最小数量,并仅在该数量发生时收集您的时间跨度。

可以查询系统性能指标。System.Diagnostics.PerformanceCounter类的msdn文档有一些示例。使用这个类,您可以查询"'Process(your_process_name)'% Processor Time"。这是秒表的另一种选择,但我认为只是使用秒表并平均多次运行时间是一个完美的方法。

如果您需要的是一个更高分辨率的秒表,因为您正在尝试测量cpu时间的一小部分,那么您可能会对高性能计数器感兴趣。