You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#如何测量方法平均执行时间并提升测量结果的准确度

C# 方法执行时间测量工具优化方案

你的现有实现已经可以完成基础测量需求,可通过以下方案提升测量准确度,也可根据需求选择更适配的实现逻辑:

核心优化点

  • 新增预热环节:首次调用目标方法时会触发JIT编译,带来额外开销,建议正式统计前先空跑1次目标方法,不将该次耗时计入统计,避免JIT编译拉高平均耗时。
  • 优化GC干扰处理:你当前仅在测量开始前做一次GC回收,如果目标方法运行过程中会生成大量托管对象,上一次执行残留的对象可能导致本次执行过程中触发GC,影响计时结果。可选择每次执行目标方法前都强制完成GC回收,也可以额外统计GC分配量辅助判断结果准确性。
  • 提升计时精度:当前使用ElapsedMilliseconds仅能拿到毫秒级结果,如果目标方法执行耗时较短,误差会非常大,建议改用微秒级的Elapsed.TotalMicroseconds,或者直接通过Stopwatch.ElapsedTicks结合Stopwatch.Frequency计算高精度耗时。
  • 优化统计逻辑:仅计算平均值抗干扰性较差,系统调度、后台进程突发占用资源都可能导致某一次计时结果异常偏高,建议统计时剔除最高、最低的1-2次异常值后再计算平均值,也可以补充输出最大、最小耗时作为参考。
  • 降低系统调度干扰:测量时可临时提升当前线程的优先级,减少CPU被系统调度走的概率,测量完成后再恢复原有优先级即可。

优化后实现代码

public static void Measure(Action action, int runCount = 10)
{
    // 预热:空跑一次,触发JIT编译
    action();
    
    // 提前清理GC,避免初始GC干扰
    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();

    List<long> timeConsumptions = new List<long>(runCount);
    Console.WriteLine("开始测量...");

    // 保存原有线程优先级,测量结束后恢复
    var originalPriority = Thread.CurrentThread.Priority;
    try
    {
        Thread.CurrentThread.Priority = ThreadPriority.Highest;
        
        for (int i = 0; i < runCount; i++)
        {
            // 每次执行前清理GC,避免上一轮残留影响
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            
            Stopwatch watch = Stopwatch.StartNew();
            action();
            watch.Stop();
            
            long microSeconds = watch.Elapsed.Ticks / (Stopwatch.Frequency / 1000000);
            timeConsumptions.Add(microSeconds);
            Console.WriteLine($"第{i+1:D2}次执行 耗时:{microSeconds} μs / {(double)microSeconds/1000:F3} ms");
        }
    }
    finally
    {
        // 恢复线程优先级
        Thread.CurrentThread.Priority = originalPriority;
    }

    // 剔除最高最低值计算平均
    timeConsumptions.Sort();
    var validList = timeConsumptions.Skip(1).Take(runCount - 2).ToList();
    long average = (long)validList.Average();
    Console.WriteLine($"\n统计结果(已剔除1次最高、1次最低值):");
    Console.WriteLine($"最小耗时:{timeConsumptions[0]} μs / {(double)timeConsumptions[0]/1000:F3} ms");
    Console.WriteLine($"最大耗时:{timeConsumptions[^1]} μs / {(double)timeConsumptions[^1]/1000:F3} ms");
    Console.WriteLine($"平均耗时:{average} μs / {(double)average/1000:F3} ms");
}

调用方式和原有逻辑一致:

int runTimes = 10;
Utils.Measure(() => 
{  
    MyMethod(arr);
}, runTimes);

其他可选实现思路

如果需要更专业的基准测试,比如需要统计不同参数下的性能、内存分配、分支预测命中率等数据,可使用专门的基准测试库,不用自己重复造轮子。如果仅需要轻量的10次平均耗时统计,上述优化后的方法已经足够准确。

内容的提问来源于stack exchange,提问作者ZihamZuhair

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 05:12:02