如何使用C# Stopwatch 测量微秒级精确度

 更新时间:2021年03月04日 09:44:44   作者:黑暗执行绪  
这篇文章主要介绍了如何使用C# Stopwatch 测量微秒精确度,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下

跟同事讨论到- 用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数)。

第二版改用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

以上就是如何使用C# Stopwatch 测量微秒精确度的详细内容,更多关于C# Stopwatch 测量微秒精确度的资料请关注脚本之家其它相关文章!

相关文章

  • Unity实现大转盘的简单笔记

    Unity实现大转盘的简单笔记

    这篇文章主要为大家分享了Unity实现大转盘的简单笔记,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-02-02
  • 详解C#多线程之线程同步

    详解C#多线程之线程同步

    本文主要介绍了C#线程同步的相关知识。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • C#中三种Timer计时器的详细用法

    C#中三种Timer计时器的详细用法

    这篇文章介绍了C#中三种Timer计时器的详细用法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • C# List介绍及具体用法

    C# List介绍及具体用法

    这篇文章主要介绍了C# List介绍及具体用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • C# 中的委托详细解析与完整应用小结

    C# 中的委托详细解析与完整应用小结

    C#委托是一种类型安全的函数指针,允许将方法作为参数传递或赋值给变量,它在事件处理、回调和异步编程中广泛应用,本文详细介绍了委托的基本概念、用法和高级应用,感兴趣的朋友一起看看吧
    2025-03-03
  • 字符串阵列String[]转换为整型阵列Int[]的实例

    字符串阵列String[]转换为整型阵列Int[]的实例

    下面小编就为大家分享一篇字符串阵列String[]转换为整型阵列Int[]的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • C#使用webbrowser的常见用法实例

    C#使用webbrowser的常见用法实例

    这篇文章主要介绍了C#使用webbrowser的常见用法,涉及C#使用webbrowser实现判断网络连接、模拟登陆、点击等常用技巧,需要的朋友可以参考下
    2015-08-08
  • C#控制键盘按键的常用方法

    C#控制键盘按键的常用方法

    这篇文章主要介绍了C#控制键盘按键的常用方法,涉及C#针对键盘大写、滚动、数字的开启与锁定等功能,非常简单实用,需要的朋友可以参考下
    2015-05-05
  • C# 获取 PC 序列号的方法示例

    C# 获取 PC 序列号的方法示例

    这篇文章主要介绍了C# 获取 PC 序列号的方法示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07
  • C#中CompareTo的用法小结

    C#中CompareTo的用法小结

    CompareTo方法通常用于比较当前对象与另一个对象的顺序,本文主要介绍了C#中CompareTo的用法小结,具有一定的参考价值,感兴趣的可以了解一下
    2025-04-04

最新评论