这里没有答案,顶多给你几个值得一试的猜想。
由装配脑袋、Allen Lee、FantasySoft、idior等合作翻译,已于2008年1月上市。
已于2009年1月上市。
.NET v2.0 下的高精度计数器 —— Stopwatch [.NET v2.0, C#]
Written by Allen Lee
无论你是搞技术研究还是搞项目开发,高精度的时间测量在很多场合下都是必需的。xiaotie 在其《dotnet下时间精度测量》提到了一个 QueryPerfCounter,它对目前还在使用 Microsoft .NET Framework v1.1 的开发人员来说的确是一个好帮手。但若你已经用上了 Microsoft .NET Framework v2.0,那么 Stopwatch 将会成为你进行高精度时间测量的不二选择。
1. 测试 Stopwatch
这里,我借用一下 xiaotie 在《dotnet下时间精度测量》的测试代码,并给出对应的运行结果:
从测试结果中可以看到,Stopwatch 绝对能够满足挑剔的你!怎么样?手痒了吗?
2. 应用 Stopwatch
Stopwatch 位于 System.Diagnostics 命名空间中,它的使用方法非常简单,只要你会用一般的计时器,你就会使用它。
2.1 创建实例
你可以通过 new 或者 Stopwatch.StartNew() 来创建一个 Stopwatch 实例:
使用 StartNew() 会创建一个 Stopwatch 实例并马上开始计时,即等效于如下代码:
2.2 测量时间
2.3 应用示例
微软官方提供了一系列示范程序用于演示 Visual Studio 2005,其中 Basic Class Library 部分带有一个 Stopwatch 的 Windows Forms 示例程序,你可以到 101 Samples for Visual Studio 2005 下载示例代码。
3. 深入 Stopwatch
Stopwatch 内部也调用了 QueryPerformanceCounter() 和 QueryPerformanceFrequency() 两个函数,与 QueryPerfCounter 不同的是,当 Stopwatch 检测到当前的系统和硬件不支持高精度的计数器时,它将转用我们所熟悉的 DateTime 做法。
Stopwatch 在其静态构造器中调用 QueryPerformanceFrequency(),透过该函数的返回值判断当前的系统和硬件是否支持高精度的计数器,并设置 IsHighResolution 属性的值。Stopwatch 内部用于计算时间间隔的主要方法都会根据 IsHighResolution 的值来选择合适的计算方法。有兴趣的话,你可以使用 Reflector 探究一下 Stopwatch 的内部。
posted on 2005-08-16 22:23 Allen Lee 阅读(4593) 评论(10) 编辑 收藏 网摘 所属分类: .NET
当 Stopwatch 检测到当前的系统和硬件不支持高精度的计数器时,它将转用我们所熟悉的 DateTime 做法。 ??????? 这句没明白,什么样系统和硬件会不支持高精度计数器? 回复 引用 查看
To 萧寒: 这句话只是描述了 Stopwatch 内部的处理方式,说实话,我也没有见过现在有什么硬件是支持 .NET 却不支持高精度计数器。至于 Stopwatch 的这种做法是保险还是是多余,就见仁见智了。值得注意的是,Stopwatch 不支持 .NET CF。 回复 引用 查看
我刚才测试了一下。Stopwatch和QueryPerfCounter精度是一样的(测试ElapsedTicks)。Stopwatch和QueryPerfCounter我测试结果每次stop()和start()调用耗时是4个ticks,最小时间单位1个tick,对我笔记本来说是270ns。 回复 引用
我到是把stopwatch的代码reflector出来了,不过有个类不可用,说是什么private什么的。最后也就没有继续下去了。 回复 引用 查看
To yinh:你所指的那个类应该就是 SafeNativeMethods,它被声明为 internal,对于 Stopwatch 来说,该类的有效成分是:(该类其他成分略去)internal static class SafeNativeMethods { [DllImport("kernel32.dll")] public static extern bool QueryPerformanceCounter(out long value); [DllImport("kernel32.dll")] public static extern bool QueryPerformanceFrequency(out long value);} 回复 引用 查看
To yinh:
你所指的那个类应该就是 SafeNativeMethods,它被声明为 internal,对于 Stopwatch 来说,该类的有效成分是:(该类其他成分略去)
最后测试了一下用汇编。 (1) extern "C" { __declspec(dllexport) unsigned __int64 GetCycleCount(void) { _asm _emit 0x0F; _asm _emit 0x31; } } (2) public sealed class Enviroment { [DllImport("TimeStamp.dll")] public static extern long GetCycleCount(); [DllImport("Kernel32.dll")] private static extern bool QueryPerformanceFrequency(out long lpFrequency); [DllImport("KERNEL32")] private static extern bool QueryPerformanceCounter(out long lpPerformanceCount); } (3) static void Main(string[] args) { long start,end; start=Enviroment.GetCycleCount(); end=Enviroment.GetCycleCount(); for(int i=0;i<1000;i++) { start=Enviroment.GetCycleCount(); end=Enviroment.GetCycleCount(); Console.WriteLine(end-start); } } 这个东西行为很古怪,随着i增加,end-start慢慢的从3000多收敛到247.也就是说测量绝对的时间,误差在200ns上下,测定相对时间,通过校准可以下降到10ns以下。一次调用要花这个多时钟周期呀!不知道还又没办法进一步提高。 回复 引用
大哥啊,下次能把原文地址帖上吗?? 真是好东西啊 回复 引用
遥测导弹飞人马,如果,你真有个雷达, 2008 可能用得上这套 我就的 System.Environment.TickCount Do Dim i as Uinteger Loop Until i > xxxx System.Environment.TickCount 循环 10^n 整数不久行了 回复 引用
在 Windows 中跟踪时间有几种不同的方法: 1. System.Windows.Forms.Timer:这是 Windows 编程中最常用的计时器。虽然它很容易使用,但它只有 1/18 秒的分辨率。由于我们每秒最多可以有一千帧,因此这样的分辨率对于游戏程序而言不是太令人满意。 2. timeGetTime:这种 Windows DLL 在有些版本的 Windows 上提供 1 微秒的分辨率,在 Windows NT 上为 5 微秒。这种变化太大,而且我们确实不想通过检查游戏运行的操作系统来查看我们是否需要调整计时器的值。 3. System.TickCount:这种托管调用返回滴答数(表示毫秒数)。这接近于我们的期望,但我们可以做得更好。 4. QueryPerformanceCounter:这是首选使用的计时器,其分辨率小于 1 微秒。这是在游戏开发中最常用的计时器。 编写最后一种计时器需要一定的技巧,因为它要求调用 Windows 中的一个低级 DLL(kernel32,如果您需要知道)。 回复 引用
有了stopwatch根本就不需要去声明windows api的2个高精度计时器函数Stopwatch timer = new Stopwatch();timer.Start();DoSomething();timer.Stop();Console.WriteLine("elapsed time:{0}ms", (timer.ElapsedTicks+0.0f)*1000/Stopwatch.Frequency); 回复 引用
Powered by: 博客园 Copyright © Allen Lee