C#中的高精度计时方法(纳秒级别计时)

时间:2023-01-30 19:31:41

QueryPerformanceCounter获得CPU执行计数值

__int64 startTime

if(QueryPerformanceCounter((LARGE_INTEGER *)&startTime))

printf("QueryPerformanceCounter:%lf/n",(double)startTime);

http://www.cnblogs.com/wubiyu/archive/2008/09/11/1289034.html

 

精确的时间计量方法在某些应用程序中是非常重要的。常用的 Windows API 方法 GetTickCount() 返回系统启动后经过的毫秒数。另一方面,GetTickCount() 函数仅有 1ms 的分辨精度,很不精确。

故而,我们要另外寻找一种方法来精确测量时间。

Win32 API 使用 QueryPerformanceCounter() 和 QueryPerformanceFrequency() 方法支持高精度计时。这些方法,比“标准的”毫秒精度的计时方法如 GetTickCount() 之类有高得多的精度。另一方面来说,在 C# 中使用“非托管”的 API 函数会有一定的开销,但比起使用一点都不精确的 GetTickCount() API 函数来说要好得多了。

第一个函数 QueryPerformanceCounter() 查询任意时刻高精度计数器的实际值。第二个函数 QueryPerformanceFrequency() 返回高精度计数器每秒的计数值。为了获得某一代码段经历的时间,你需要获得代码段开始前和结束后这两个计时时刻的高精度计数器实际值。这两个值的差指出了代码段执行所经历的时间。

然后通过将差除以每秒计数值(高精度计时器频率),就可以计算经过的时间了。

duration = (stop - start) / frequency 
经过时间 = (停止时间 - 开始时间) / 频率

需要关于 QueryPerformanceCounter 和 QueryPerformanceFrequency 的更多信息,请参阅 MSDN 文档。

代码 
下面的类实现了 QueryPerformanceCounter() 和 QueryPerformanceFrequency() API 函数的功能。

 

using System; 
using System.Runtime.InteropServices; 
using System.ComponentModel; 
using System.Threading;

namespace Win32 

    internal class HiPerfTimer 
    { 
        [DllImport("Kernel32.dll")] 
        private static extern bool QueryPerformanceCounter( 
            out long lpPerformanceCount);

        [DllImport("Kernel32.dll")] 
        private static extern bool QueryPerformanceFrequency( 
            out long lpFrequency);

        private long startTime, stopTime; 
        private long freq;

        // 构造函数 
        public HiPerfTimer() 
        { 
            startTime = 0; 
            stopTime  = 0;

            if (QueryPerformanceFrequency(out freq) == false) 
            { 
                // 不支持高性能计数器 
                throw new Win32Exception(); 
            } 
        }

        // 开始计时器 
        public void Start() 
        { 
            // 来让等待线程工作 
            Thread.Sleep(0);

            QueryPerformanceCounter(out startTime); 
        }

        // 停止计时器 
        public void Stop() 
        { 
            QueryPerformanceCounter(out stopTime); 
        }

        // 返回计时器经过时间(单位:秒) 
        public double Duration 
        { 
            get 
            { 
                return (double)(stopTime - startTime) / (double) freq; 
            } 
        } 
    } 
}

使用这个类很简单。只需要创建一个 HiPerfTimer 的实例,然后调用 Start() 开始计时,Stop() 停止计时。要获得经过的时间,调用 Duration() 函数即可。

参考下面的例子。 HiPerfTimer pt = new HiPerfTimer();     // 创建新的 HiPerfTimer 对象 
pt.Start();                             // 启动计时器 
Console.WriteLine("Test/n");            // 需要计时的代码 
pt.Stop();                              // 停止计时器 
Console.WriteLine("Duration: {0} sec/n", 
     pt.Duration); // 打印需要计时部分代码的用时

下面的图片是该例子在我系统上的输出。

C#中的高精度计时方法(纳秒级别计时)

高精度计时

private void button1_Click_1(object sender, EventArgs e)

{

    System.Diagnostics.Stopwatch MyWatch = new System.Diagnostics.Stopwatch();

    MyWatch.Start();

    System.Threading.Thread.Sleep(100);

    MyWatch.Stop();

    MessageBox.Show( MyWatch.ElapsedMilliseconds.ToString() + "毫秒");

}

////当计算时间进入纳秒级时,Stopwatch(最小精是毫秒) 是无法计时的,还Environment.TickCount获取系统启动应用程序的毫秒级。对于要求不高,计算时间在毫秒级可以用Stopwatc或Environment.TickCount。若有计算纳秒级的计时就只能使用上面第一种方法。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wenrenhua08/archive/2008/09/15/2903780.aspx

 

 

.Net 实现纳秒级别计算 
1)建立VC.NET 托管类库

using namespace System;

namespace MLTimerDot

{

        //得到计算机启动到现在的时钟周期

        unsigned __int64 GetCycleCount(void)

        {

                _asm  _emit 0x0F

                _asm  _emit 0x31

        }

        //声明 .NET 类

        public __gc class MLTimer

        {

        protected:

                UInt64 m_startcycle;

                UInt64 m_overhead;

        public:

                MLTimer(void)

                {

                        //为了计算更精确取得调用一个 GetCycleCount() 的时钟周期

                        m_overhead=0;

                        Start();

                        m_overhead=Stop();

                }

                //计算停止

                UInt64 Stop(void)

                {

                        return GetCycleCount()-m_startcycle-m_overhead;

                }

                //计算开始

                void Start(void)

                {

                        m_startcycle=GetCycleCount();

                }

                 __property virtual UInt64 get_Overhead()

                 {

                        return m_overhead;

                 }

        };

}

2)测试代码

//C# 引用后放一个Button 测试

private void button1_Click(object sender, System.EventArgs e)

{

        MLTimerDot.MLTimer timer=new MLTimerDot.MLTimer();

        timer.Start();

        Thread.Sleep(1000);

        UInt64 cpuspeed10=(ulong)(timer.Stop()/100000); //通过这个可以算出 CPU 的mhz

        timer.Start();//开始

        //测试代码(测试声明一个DataTable 用的时间)

        DataTable td= new DataTable();

        UInt64 time1=timer.Stop();//停止

        String s= String.Format("CPU {0}.{1} mhz/n声明 MLTimer 类的系统开销 {2:n} 时钟周期/n本操作系统开销 {3:n} 个时钟周期/n使用 {4:n} ns",

                cpuspeed10/10,cpuspeed10%10,timer.Overhead,

                time1,

                time1*10000/cpuspeed10);

        MessageBox.Show(s);

}

/*-------------------------------------------------------------------------------------------

MLTimer 类库必须使用VC。NET 开发,只有VC。NET 可以坠入汇编(爽)。

编译完成可以在任何.Net语言下使用(当然也可以封装成API , 或 com 组件)。

想想以后可以在网页上显示:

你本次查询使用了:xxxxx 纳秒。

是不是很爽^_^,当然还可以进行一些精密的计算,

这是在下在CSDN第2次发表文章。希望大家可以喜欢。

演示代码:

http://www.kairuisoft.com/uploads/MLTimerDot.rar

声明:本源代码你可以用于任何用途,不过用于商业程序时请通知本人,谢谢。QQ 65423574

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/FlashElf/archive/2004/06/23/24336.aspx