内容简介:跟同事討論到 - 用 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.
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- RecyclerView使用指南(一)—— 基本使用
- 如何使用Meteorjs使用URL参数
- 使用 defer 还是不使用 defer?
- 使用 Typescript 加强 Vuex 使用体验
- [译] 何时使用 Rust?何时使用 Go?
- UDP协议的正确使用场合(谨慎使用)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
ACM程序设计培训教程
吴昊 / 中国铁道 / 2007-8 / 28.0
《ACM程序设计培训教程》不是这些专门问题的教科书,所以对这些问题所涉及知识的介绍不多,主要是分析一个个案例,介绍专属于ACM程序设计的方法和技巧。一起来看看 《ACM程序设计培训教程》 这本书的介绍吧!