野人獻曝 - 極簡風格 .NET Stopwatch 計時法

在 .NET 要測量執行時間,Stopwatch 是最簡單直覺的做法,像這樣:

Stopwatch sw = new Stopwatch();
sw.Start();
//...執行要測試的動作
sw.Stop();
//將測得秒數輸出到Console、Debug或Log檔
Console.WriteLine($"Time={sw.ElapsedMilliseconds:n0}ms");

說起來不複雜,但一但測量對象變多,專案將充斥大量 Stopwatch 建立、開始、結束以及記錄時間的程式碼。遇到大範圍要計時,內部也要分段計時的需求,還得宣告多個 Stopwatch 物件並注意命名不能重複。再則,若想透過 config 統一啟用或停用所有計時功能,在每一段計時程式都要多加 if,很醜。

基於上述考量,我會寫成共用函式或程式庫集中程式碼,但用起來還是有點囉嗦,直到最近我想到一個好點子,將計時函式寫成實做 IDisposable 的專用物件,建構時建立 Stopwatch 並 Start() 開始計時,在 Dispose() 時 Stop() 並輸出計時結果:

    /// <inheritdoc />
    /// <summary>
    /// 執行時間測量範圍(自動使用Stopwatch計時並寫Log)
    /// </summary>
    public class TimeMeasureScope : IDisposable
    {
        private readonly Stopwatch stopwatch = new Stopwatch();
        private readonly string _title;
 
        public static bool Disabled = false;
 
        /// <summary>
        /// 建構式
        /// </summary>
        /// <param name="title">範圍標題</param>
        public TimeMeasureScope(string title)
        {
            if (Disabled) return;
            _title = title;
            stopwatch.Start();
        }
 
        /// <inheritdoc />
        public void Dispose()
        {
            if (Disabled) return;
            stopwatch.Stop();
            //TODO: 實務上可將效能數據寫入Log檔
            Console.WriteLine(
                $"{_title}|{stopwatch.ElapsedMilliseconds:n0}ms");
        }
    }

如此,使用 using 關鍵字可控制 TimeMeasureScope 生命週期以及計時起點與終點,從 using 開始大括號「{」開始計時,遇到結束大括號「}」截止並輸出計時結果。這樣子,只需將要測量的程式碼片段用 using (var scope = new TimeMeasureScope()) 包起來就能自動計時,而且支援巢狀套用,例如以下這個無聊範例:

唯一的副作用是 using {} 會改變範圍內宣告變數的有效範圍,無法供外部叫用,部分變數可能需調整宣告位置,但問題不大。

用起來很簡單吧,實際在專案用過感覺不錯,野人現曝一下~

歡迎推文分享:
Published 09 January 2018 08:41 PM 由 Jeffrey
Filed under: ,
Views: 3,818



意見

# kkbruce said on 09 January, 2018 08:53 PM

這招好。

但這時候也能感受 ActionFilter 的強大了。

:-)

# CIHsieh said on 09 January, 2018 09:13 PM

//野人獻曝

public static TimeSpan Measure(Action action)

{

   var stopwatch = new Stopwatch();

   stopwatch.Start();

   action?.Invoke();

   stopwatch.Stop();

   return stopwatch.Elapsed;

}

# wellxion said on 10 January, 2018 02:52 AM

用using控制的話

會不會有機會無法及時被釋放的問題?

這樣的話統計出來的時間可能會有誤差

# Jeffrey said on 10 January, 2018 05:16 AM

to CIHsieh,這方法也不錯,感謝分享。

to wellxion,我倒真的沒考慮到這種可能,能否提供無法及時釋放的案例? 我來研究看看。

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<January 2018>
SunMonTueWedThuFriSat
31123456
78910111213
14151617181920
21222324252627
28293031123
45678910
 
RSS
創用 CC 授權條款
【廣告】
twMVC
最新回應

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication