首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

使用 Stopwatch 精準測量程式碼效能

     編輯:關於.NET

現代 CPU 多核心、超標量架構、快取與指令管線導致同一程式碼執行時間波動高達 25-30%。本文介紹如何配置 System.Diagnostics.Stopwatch 達到 0.1-0.2% 測量精度,使演算法比較具備統計意義。

干擾因素與對策

干擾源對策代碼
CPU 核心切換鎖定處理器親和性Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(2); // 僅使用第 2 核心
其他執行緒/進程搶佔提升進程與執行緒優先權Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
Thread.CurrentThread.Priority = ThreadPriority.Highest;
冷啟動效應(JIT、快取預熱)執行暖機迴圈至穩定見下方完整範例
JIT 優化移除無用運算保留運算結果並最終輸出result ^= TestFunction(...); Console.WriteLine(result);

完整基準測試範例

using System;
using System.Diagnostics;
using System.Threading;

namespace PreciseMeasure {
    class Program {
        static void Main(string[] args) {
            Stopwatch sw = new Stopwatch();
            long seed = Environment.TickCount;
            long result = 0;
            int count = 100_000_000;

            Console.WriteLine("20 Tests WITHOUT correct preparation");
            for (int i = 0; i < 20; ++i) {
                sw.Reset(); sw.Start();
                result ^= TestFunction(seed, count);
                sw.Stop();
                Console.WriteLine($"Ticks: {sw.ElapsedTicks}  mS: {sw.ElapsedMilliseconds}");
            }

            // === 正確配置 ===
            Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(2);
            Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
            Thread.CurrentThread.Priority = ThreadPriority.Highest;

            Console.WriteLine("\n20 Tests WITH correct preparation");
            Console.WriteLine("Warmup...");
            sw.Reset(); sw.Start();
            while (sw.ElapsedMilliseconds < 1200) { // 1.2 秒暖機
                result = TestFunction(seed, count);
            }
            sw.Stop();

            for (int i = 0; i < 20; ++i) {
                sw.Reset(); sw.Start();
                result ^= TestFunction(seed, count);
                sw.Stop();
                Console.WriteLine($"Ticks: {sw.ElapsedTicks}  mS: {sw.ElapsedMilliseconds}");
            }
            Console.WriteLine(result); // 防止編譯器優化移除
        }

        public static long TestFunction(long seed, int count) {
            long result = seed;
            for (int i = 0; i < count; ++i)
                result ^= i ^ seed; // 簡單位運算負載
            return result;
        }
    }
}

實測結果對比

未配置(結果不可靠)

Ticks: 1580367 mS: 572  <-- 最高
Ticks: 1577003 mS: 571
...
Ticks: 1112012 mS: 402  <-- 最低
...
Ticks: 1349507 mS: 488

執行時間分佈 **402ms ~ 572ms**,差距 **170ms (42%)**,無法用於比較。

正確配置後(高精度)

Ticks: 1110518 mS: 402
Ticks: 1110540 mS: 402
...
Ticks: 1110684 mS: 402  <-- 最高
...
Ticks: 1110433 mS: 402  <-- 最低

20 次測試皆為 **402ms**,僅 **Tick 差異 251 (0.02%)**,對應 **0.09ms** 差異,極適合演算法基準測試。

關鍵洞察

未配置的「最好成績」仍比配置後的「最差成績」慢。
CPU 上下文切換與核心遷移對效能影響極大,嚴格的測試環境控制是精準測量的前提。

參考英文原文:Stopwatch Measure Precise

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved