http://www.cnblogs.com/jintianhu/archive/2010/09/01/1815031.html

参考: https://www.cnblogs.com/kissdodog/archive/2013/05/20/3088874.html

以下所有代码运行环境:Windows 2003, Intel(R) Core(TM) 2 Duo CPU E8400 @  3.00GHz 2.99GHz,2.96GB内存

根据综合网上的一些文章,精确计时主要有以下几种方式

1 调用WIN API中的GetTickCount

[DllImport("kernel32")]
static extern uint GetTickCount();

从操作系统启动到现在所经过的毫秒数,精度为1毫秒,经简单测试发现其实误差在大约在15ms左右

缺点:返回值是uint,最大值是2的32次方,因此如果服务器连续开机大约49天以后,该方法取得的返回值会归零

用法:

1
2
3
uint s1 = GetTickCount();
Thread.Sleep(2719);
Console.WriteLine(GetTickCount() - s1);  //单位毫秒

2 调用WIN API中的timeGetTime  推荐

[DllImport("winmm")]
static extern uint timeGetTime();

常用于多媒体定时器中,与GetTickCount类似,也是返回操作系统启动到现在所经过的毫秒数,精度为1毫秒。

一般默认的精度不止1毫秒(不同操作系统有所不同),需要调用timeBeginPeriod与timeEndPeriod来设置精度

[DllImport("winmm")]
static extern void timeBeginPeriod(int t);
[DllImport("winmm")]
static extern void timeEndPeriod(int t);

缺点:与GetTickCount一样,受返回值的最大位数限制。

用法:

1
2
3
4
5
timeBeginPeriod(1);
uint start = timeGetTime();
Thread.Sleep(2719);
Console.WriteLine(timeGetTime() - start);  //单位毫秒
timeEndPeriod(1);

3 调用.net自带的方法System.Environment.TickCount

获取系统启动后经过的毫秒数。经反编译猜测它可能也是调用的GetTickCount,但是它的返回值是int,而GetTickCount与timeGetTime方法的原型中返回值是DWORD,对应C#中的uint,难道.NET对System.Environment.TickCount另外还做了什么处理么?
缺点:与GetTickCount一样,受返回值的最大位数限制。

用法:

1
2
3
int aa = System.Environment.TickCount;
Thread.Sleep(2719);
Console.WriteLine(System.Environment.TickCount - aa); //单位毫秒

:经过测试,发现GetTickCount、System.Environment.TickCount也可以用timeBeginPeriod与timeEndPeriod来设置精度,最高可将精度提高到1毫秒。不知是什么原因?

4 调用WIN API中的QueryPerformanceCounter

[DllImport("kernel32.dll ")]
static extern bool QueryPerformanceCounter(ref long lpPerformanceCount);

用于得到高精度计时器(如果存在这样的计时器)的值。微软对这个API解释就是每秒钟某个计数器增长的数值。
如果安装的硬件不支持高精度计时器,函数将返回false需要配合另一个API函数QueryPerformanceFrequency。

[DllImport("kernel32")]
static extern bool QueryPerformanceFrequency(ref long PerformanceFrequency);

QueryPerformanceFrequency返回硬件支持的高精度计数器的频率,如果安装的硬件不支持高精度计时器,函数将返回false。

用法:

1
2
3
4
5
6
7
long a = 0;
QueryPerformanceFrequency(ref a);
long b = 0, c = 0;
QueryPerformanceCounter(ref b);
Thread.Sleep(2719);
QueryPerformanceCounter(ref c);
Console.WriteLine((c - b) / (decimal)a);  //单位秒

精度为百万分之一秒。而且由于是long型,所以不存在上面几个API位数不够的问题。

缺点:在一篇文章看到,该API在节能模式的时候结果偏慢,超频模式的时候又偏快,而且用电池和接电源的时候效果还不一样(笔记本)
原文地址:http://delphi.xcjc.net/viewthread.php?tid=1570
未经过超频等测试,如果是真的,那该API出来的结果就可能不准。

5 使用.net的System.Diagnostics.Stopwatch类    推荐

Stopwatch 在基础计时器机制中对计时器的刻度进行计数,从而测量运行时间。如果安装的硬件和操作系统支持高分辨率性能的计数器,则 Stopwatch 类将使用该计数器来测量运行时间;否则,Stopwatch 类将使用系统计数器来测量运行时间。使用 Frequency 和 IsHighResolution 两个静态字段可以确定实现 Stopwatch 计时的精度和分辨率。

实际上它里面就是将QueryPerformanceCounter、QueryPerformanceFrequency两个WIN API封装了一下,如果硬件支持高精度,就调用QueryPerformanceCounter,如果不支持就用DateTime.Ticks来计算。

用法:

1
2
3
4
5
Stopwatch sw = new Stopwatch();
sw.Start();
Thread.Sleep(2719);
sw.Stop();
Console.WriteLine(sw.ElapsedTicks / (decimal)Stopwatch.Frequency);
 
//获取刻度值  ,计算毫秒数
long start=Stopwatch.GetTampstamp()
double dbl=(Stopwatch.GetTampstamp()-start)*1000/Stopwatch.frequency;
 
 

6 使用CPU时间戳进行更高精度计时

原文地址:http://www.chinaunix.net/jh/23/110190.html

该方法的原理我不是很明白,硬件知识太匮乏了。精度是ns

在C#中要用该方法必须先建立一个托管C++项目(因为要内嵌汇编),编译成DLL供c#调用,有点麻烦。

C++代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// MLTimerDot.h
 
#pragma once
 
using namespace System;
 
namespace MLTimerDot {
 
        //得到计算机启动到现在的时钟周期
        unsigned __int64 GetCycleCount(void)
        {
                _asm  _emit 0x0F
                _asm  _emit 0x31
        }
 
 
        //声明 .NET 类
        public __gc class MLTimer
        {
        public:
                MLTimer(void)
                {
                       
                }
 
                //计算时钟周期
                UInt64 GetCount(void)
                {
                        return GetCycleCount();
                }
 
        };
}

C#调用:

1
2
3
4
5
6
7
long a = 0;
QueryPerformanceFrequency(ref a);
 
MLTimerDot.MLTimer timer = new MLTimerDot.MLTimer();
ulong ss= timer.GetCount();
Thread.Sleep(2719);
Console.WriteLine((timer.GetCount() - ss) / (decimal)a);

缺点:和QueryPerformanceCounter一样,结果不太稳定。

我的结论:常规应用下timeGetTime完全够用了,将精度调到1毫秒,大部分境况都够用。System.Diagnostics.Stopwatch由于调用方便,也推荐使用。

 
 
标签: c#

C#中精确计时的一点收获 Stopwatch的更多相关文章

  1. C#中精确计时的一点收获 【转】

    C#中精确计时的一点收获 [转] 以下所有代码运行环境:Windows 2003, Intel(R) Core(TM) 2 Duo CPU E8400 @  3.00GHz 2.99GHz,2.96G ...

  2. C#中精确计时的一点收获

    以下所有代码运行环境:Windows 2003, Intel(R) Core(TM) 2 Duo CPU E8400 @  3.00GHz 2.99GHz,2.96GB内存 根据综合网上的一些文章,精 ...

  3. c#多态之抽象类与接口的一点收获~~

    多态之抽象类与接口的相似点及不同点,刚学习的一点收获,或许不是很完整,借鉴看视频及一些被人写的文章自己写的下的一些心得!以便之久复习使用! 一.抽象类 (1) 抽象方法只作声明,而不包含实现,可以看成 ...

  4. C语言中常用计时方法总结

    转自:http://blog.csdn.net/fz_ywj/article/details/8109368 C语言中常用计时方法总结 1. time() 头文件:time.h 函数原型:time_t ...

  5. windows下的C/C++精确计时

    由于我要测试线性筛法的速度,用上了C/C++精确计时.此时传统的clock()方法不够用了,我们需要另一种测量的办法,即CPUTicks/CPUFreq.如何实现呢? #include <win ...

  6. C# 广播TS流精确计时发送

    广播传输相关的项目,需求是UDP发送TS到IP/ASI网关,网关经过ASI输出到激励器,再由激励器通过射频天线输出,接收端为终端机顶盒. 因为以前没有怎么接触过广播相关的东西,一开始认为用C#写个UD ...

  7. Golang中WaitGroup使用的一点坑

    Golang中WaitGroup使用的一点坑 Golang 中的 WaitGroup 一直是同步 goroutine 的推荐实践.自己用了两年多也没遇到过什么问题.直到一天午睡后,同事扔过来一段奇怪的 ...

  8. [转载]对iOS开发中内存管理的一点总结与理解

    对iOS开发中内存管理的一点总结与理解   做iOS开发也已经有两年的时间,觉得有必要沉下心去整理一些东西了,特别是一些基础的东西,虽然现在有ARC这种东西,但是我一直也没有去用过,个人觉得对内存操作 ...

  9. 【ABAP系列】SAP ABAP中关于commit的一点解释

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP中关于commi ...

随机推荐

  1. ASP.NET Core MVC 502 bad gateway 超时如何处理

    在网页程序运行需要较长时间运行的时候,ASP.NET Core MVC会出现502 bad gateway请求超时情况.一般默认的超时时间都比较短,我们需要在 web.config 中配置一下.其中  ...

  2. Vue axios异步获取后台数据alert提示undefined

    记录一个小问题,关于分页查询套餐 前台通过axios异步请求获取后台数据alert弹出数据提示undefined 下面有三个bean PageResult /** * 分页结果封装对象 */ publ ...

  3. django admin 编辑页面(change page) 自定义字段, 展示数据

    最近遇到一个需求, 需要在django 的 admin 编辑页内展示由用户上传的进行反馈的图片, 还要支持点击查看原图, 所以需要在编辑页内自定义 img 标签及 a 标签进行图片的展示及点击跳转 i ...

  4. XIX Open Cup named after E.V. Pankratiev. Grand Prix of Eurasia, Division 1.

    A 签到. C 源点向每个软件连边.把每个软件拆成对应版本数个点,每个软件向版本连边.把每个conflict也看成一个点.每个版本向它对应的conflict连边,conflict向汇点连边.没有在co ...

  5. 总结:几种生成html格式测试报告的方法

    写自动化测试时,一个很重要的任务就是生成漂亮的测试报告. 1.用junit或testNg时,可以用ant辅助生成html格式: <target name="report" d ...

  6. java注释代码规范

    //收集了一小部分,忘记的时候过来查一下 java--hadoop部分 /** * 此类用来处理DNS原始日志:统计给定域名平均响应时延 * @param Input * @param Output ...

  7. Java 的API(API: Application(应用) Programming(程序) Interface(接口))

    按 ctrl 点击查看源代码: 一.equals方法: 1.用于比较两个对象是否相同. 2.Objec 类中,若两边是引用数据类型,比较的是两个对象的内存地址. 3.Objec 类中,若两边是数值类型 ...

  8. python gevent协程

    安装 pip install gevent import gevent from gevent import monkey monkey.patch_all()#捕捉所有阻塞,不止接收gevent.s ...

  9. ES6基础-ES6 class

    作者 | Jeskson 来源 | 达达前端小酒馆 ES - Class 类和面向对象: 面向对象,即万物皆对象,面向对象是我们做开发一种的方式,开发思维,面向对象的思维中万物皆对象,以人作为例子,它 ...

  10. Java class 和public class 区别

    1.类的访问权限 为了控制某个类的访问权限,修饰词必须出现在关键字class之前.例如:public class Student {}    在编写类的时候可以使用两种方式定义类:    (A)pub ...