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

如何精准测量代码性能并降低抖动?

如何降低短代码性能测试中的抖动?

我正在研究如何测量代码段性能以最大化优化效果,测试时发现大量偏离平均值的异常值。以下代码用于测量一段运行时长约400ns的代码并统计异常值,在Windows 10笔记本(Intel CPU,已禁用超线程,.NET 6和.NET 7测试结果相近)上,约99.77%的结果低于600ns,请问该如何降低测试中的抖动?


测试代码

public static void Test()
{
    int counter;
    int c = -1;
    int[] outliers = new int[20];
    for (counter = 0; counter < 10000000; ++counter)
    {
        long startTime = Stopwatch.GetTimestamp();
        TestFunction(Environment.TickCount, 1000);
        long endTime = Stopwatch.GetTimestamp() - startTime;
        endTime *= 100;
        switch (endTime)
        {
            case > 2000:
                outliers[0]++;
                break;
            case > 1900:
                outliers[1]++;
                break;
            case > 1800:
                outliers[2]++;
                break;
            case > 1700:
                outliers[3]++;
                break;
            case > 1600:
                outliers[4]++;
                break;
            case > 1500:
                outliers[5]++;
                break;
            case > 1400:
                outliers[6]++;
                break;
            case > 1300:
                outliers[7]++;
                break;
            case > 1200:
                outliers[8]++;
                break;
            case > 1100:
                outliers[9]++;
                break;
            case > 1000:
                outliers[10]++;
                break;
            case > 900:
                outliers[11]++;
                break;
            case > 800:
                outliers[12]++;
                break;
            case > 700:
                outliers[13]++;
                break;
            case > 600:
                outliers[14]++;
                break;
            case > 500:
                outliers[15]++;
                break;
            case > 400:
                outliers[16]++;
                break;
            case > 300:
                outliers[17]++;
                break;
            case > 200:
                outliers[18]++;
                break;
            case > 100:
                outliers[19]++;
                break;

        }
    }

    for (int i = 0; i < outliers.Length; ++i)
    {
        Console.WriteLine($"For timing > {2000 - i * 100} ns count:{outliers[i]}");
    }
}
public static long TestFunction(long seed, int count)
{
    long result = seed;
    for (int i = 0; i < count; ++i)
    {
        result ^= i ^ seed; // 无意义的位运算,模拟测试代码
    }
    return result;
}

测试结果

For timing > 2000 ns count:8563
For timing > 1900 ns count:200
For timing > 1800 ns count:276
For timing > 1700 ns count:522
For timing > 1600 ns count:433
For timing > 1500 ns count:538
For timing > 1400 ns count:1742
For timing > 1300 ns count:1110
For timing > 1200 ns count:4458
For timing > 1100 ns count:4853
For timing > 1000 ns count:19
For timing > 900 ns count:16
For timing > 800 ns count:13
For timing > 700 ns count:31
For timing > 600 ns count:354
For timing > 500 ns count:2395207
For timing > 400 ns count:7581665
For timing > 300 ns count:0
For timing > 200 ns count:0
For timing > 100 ns count:0

降低测试抖动的可行方案

1. 提前预热代码

短代码首次执行会触发JIT编译、缓存加载,导致耗时异常。正式测试前先执行若干次目标函数,让运行环境进入稳定状态:

// 在Test方法的循环前添加预热逻辑
for (int warmup = 0; warmup < 1000; warmup++)
{
    TestFunction(Environment.TickCount, 1000);
}

2. 隔离系统干扰

  • 关闭后台无关程序(浏览器、杀毒软件、同步工具等),减少系统线程调度对测试的抢占。
  • 将测试进程设为高优先级:打开任务管理器,找到测试进程,右键选择「设置优先级」→「高」(谨慎使用「实时」优先级,避免系统无响应)。
  • 切换到高性能电源计划:
    1. 打开「电源选项」,选择「高性能」。
    2. 进入计划设置,将「处理器电源管理」下的「最小/最大处理器状态」均设为100%,确保CPU全程满频运行。

3. 优化测量逻辑

  • 避免在测量循环内执行I/O操作(如Console.WriteLine),所有统计完成后再统一输出结果。
  • 修正时间转换逻辑:当前用*100转换纳秒不准确,需用Stopwatch.Frequency计算真实耗时:
long elapsedTicks = endTime - startTime;
double elapsedNs = (elapsedTicks * 1_000_000_000.0) / Stopwatch.Frequency;
  • 可尝试批量测量:连续执行N次TestFunction后计算总耗时,再除以N得到单次耗时,降低Stopwatch调用的开销占比(注意批量次数不宜过多,避免缓存效应影响结果)。

4. 绑定CPU核心

将测试进程绑定到单个CPU核心,避免线程在核心间切换导致的缓存失效和调度延迟:

using System.Diagnostics;

// 在Test方法开头添加核心绑定逻辑
Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1); // 绑定到第一个逻辑核心

5. 修正异常值统计逻辑

当前的switch case顺序会导致统计重复(如>2000ns的结果只会被计入第一个case,不会触发后续的>1900等判断),可改为区间统计:

// 替换原有的switch逻辑
double elapsedNs = (endTime * 1_000_000_000.0) / Stopwatch.Frequency;
int bucket = (int)(elapsedNs / 100);
// 超出最大区间的统一计入最后一个桶
if (bucket >= outliers.Length)
{
    bucket = outliers.Length - 1;
}
outliers[bucket]++;

这样能准确统计每个100ns区间的执行次数,结果更具参考性。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 17:29:51