使用 C# Stopwatch 測量微秒精確度

栏目: ASP.NET · 发布时间: 5年前

内容简介:跟同事討論到 - 用 C# Stopwatch 取得效能數值,Stopwatch.ElapsedMilliseconds 只到毫秒(ms),如果需要更高的時間精確度(微秒μs,甚至奈秒ns),該怎麼做?原以為要費番功夫,在 Stackoverlow 查到準備測試程式如下,比較 MD5 及 SHA1 計算 1MB byte[] 雜湊值所秏費時間:

跟同事討論到 - 用 C# Stopwatch 取得效能數值,Stopwatch.ElapsedMilliseconds 只到毫秒(ms),如果需要更高的時間精確度(微秒μs,甚至奈秒ns),該怎麼做?

原以為要費番功夫,在 Stackoverlow 查到 討論 ,答案意外地簡單。

準備測試程式如下,比較 MD5 及 SHA1 計算 1MB byte[] 雜湊值所秏費時間:

static byte[] data = new byte[1024 * 1024];
static void Main(string[] args)
{
    Test1();
    Console.ReadLine();
}

private static void Test1()
{
    Console.WriteLine("Test 1");
    for (var i = 0; i < 5; i++)
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();
        var md5 = MD5.Create().ComputeHash(data);
        sw.Stop();
        Console.WriteLine($"MD5 {sw.ElapsedMilliseconds}ms");
        sw.Restart();
        var sha1 = SHA1.Create().ComputeHash(data);
        sw.Stop();
        Console.WriteLine($"SHA1 {sw.ElapsedMilliseconds}ms");
    }
}

執行結果如下:

Test 1
MD5 10ms
SHA1 2ms
MD5 2ms
SHA1 2ms
MD5 2ms
SHA1 2ms
MD5 2ms
SHA1 2ms
MD5 2ms
SHA1 2ms

有兩個問題,第一是迴圈的第一次執行因涉及 .NET 初始化,耗時會異常偏高(先做 SHA1 再做 MD5,就變成第一筆 SHA1 超過 10ms),第二是 MD5 與 SHA1 執行時間相近,都是 2ms 多,用 ElapsedMilliseconds 看不出差異。

針對首次數值耗時偏差問題,除了略過第一次數據不計,我想到的另一個解法是在 Test1() 前先跑一次 MD5.Create() 完成相關初始化。至於 ElapsedMilliseconds 看不出差異問題,改用 ElapsedTicks 是種解法,但要注意,ElaspedTicks 換算成時間單位時,不是除以 TimeSpan.TicksPerMillisecond 而是依 CPU 頻率而定,需使用 Stopwatch.Frequency (每秒 Tick 數)。參考: Stopwatch.ElapsedTicks的祕密

第二版改用 ElapsedTicks * 1000000F / Stopwatch.Frequency 計算微秒(Microsecond, μs),執行前先 MD5.Create() 暖機。

static byte[] data = new byte[1024 * 1024];
static void Main(string[] args)
{
    MD5.Create();
    Test2();
    Console.ReadLine();
}

private static void Test2()
{
    Console.WriteLine("Test 2");
    for (var i = 0; i < 5; i++)
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();
        var md5 = MD5.Create().ComputeHash(data);
        sw.Stop();
        //
        Console.WriteLine($"MD5 {sw.ElapsedTicks * 1000000F / Stopwatch.Frequency:n3}μs");
        sw.Restart();
        var sha1 = SHA1.Create().ComputeHash(data);
        sw.Stop();
        Console.WriteLine($"SHA1 {sw.ElapsedTicks * 1000000F / Stopwatch.Frequency:n3}μs");
    }
}

執行結果的第一次時間偏長問題消失,而也呈現出 SHA1 比 MD5 計算耗時的證據。而由數值來看,精確度可到 0.1μs = 100ns。

Test 2
MD5 2,402.200μs
SHA1 2,724.000μs
MD5 2,017.300μs
SHA1 2,576.900μs
MD5 2,102.100μs
SHA1 2,578.700μs
MD5 2,024.100μs
SHA1 2,600.300μs
MD5 2,008.300μs
SHA1 2,624.300μs

自己計算麻煩了點,Stopwatch 有個 Elapsed 屬性,型別為 TimeSpan,其中 TotalMilliseconds 屬性精確度即可達到 μs 及 100ns。請看第三版:

static byte[] data = new byte[1024 * 1024];
        static void Main(string[] args)
        {
            MD5.Create();
            Test3();
            Console.ReadLine();
        }
        private static void Test3()
        {
            Console.WriteLine("Test 3");
            for (var i = 0; i < 5; i++)
            {
                Stopwatch sw = new Stopwatch();
                sw.Start();
                var md5 = MD5.Create().ComputeHash(data);
                sw.Stop();
                Console.WriteLine($"MD5 {sw.Elapsed.TotalMilliseconds * 1000:n3}μs");
                sw.Restart();
                var sha1 = SHA1.Create().ComputeHash(data);
                sw.Stop();
                Console.WriteLine($"SHA1 {sw.Elapsed.TotalMilliseconds * 1000:n3}μs");
            }
        }

執行結果與第二版相同,但程式更簡單一些。

Test 3
MD5 2,423.400μs
SHA1 2,692.400μs
MD5 2,204.000μs
SHA1 2,976.800μs
MD5 2,094.500μs
SHA1 2,588.600μs
MD5 2,034.600μs
SHA1 2,598.900μs
MD5 2,029.900μs
SHA1 2,887.000μs

Tips abougt how to get microsecond or nanosecond precision with C# Stopwatch.


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

ACM程序设计培训教程

ACM程序设计培训教程

吴昊 / 中国铁道 / 2007-8 / 28.0

《ACM程序设计培训教程》不是这些专门问题的教科书,所以对这些问题所涉及知识的介绍不多,主要是分析一个个案例,介绍专属于ACM程序设计的方法和技巧。一起来看看 《ACM程序设计培训教程》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

随机密码生成器
随机密码生成器

多种字符组合密码

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具