C 中精確計時的一點收穫

2021-08-14 19:33:10 字數 3711 閱讀 3325

根據綜合網上的一些文章,精確計時主要有以下幾種方式

[dllimport("

kernel32")]

static

extern

uint gettickcount();

從作業系統啟動到現在所經過的毫秒數,精度為1毫秒,經簡單測試發現其實誤差在大約在15ms左右

缺點:返回值是uint,最大值是2的32次方,因此如果伺服器連續開機大約49天以後,該方法取得的返回值會歸零

用法:

uint s1 =gettickcount();

thread.sleep(

2719

);console.writeline(gettickcount() - s1); //

單位毫秒

[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一樣,受返回值的最大位數限制。

用法:

timebeginperiod(1

);uint start =timegettime();

thread.sleep(

2719

);console.writeline(timegettime() - start); //

單位毫秒

timeendperiod(1);

獲取系統啟動後經過的毫秒數。經反編譯猜測它可能也是呼叫的gettickcount,但是它的返回值是int,而gettickcount與timegettime方法的原型中返回值是dword,對應c#中的uint,難道.net對system.environment.tickcount另外還做了什麼處理麼?

缺點:與gettickcount一樣,受返回值的最大位數限制。

用法:

int aa =system.environment.tickcount;

thread.sleep(

2719

);console.writeline(system.environment.tickcount - aa); //

單位毫秒

注:經過測試,發現gettickcount、system.environment.tickcount也可以用timebeginperiod與timeendperiod來設定精度,最高可將精度提高到1毫秒。不知是什麼原因?

[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。

用法:

long a = 0

;queryperformancefrequency(

refa);

long b = 0, c = 0

;queryperformancecounter(

refb);

thread.sleep(

2719

);queryperformancecounter(

refc);

console.writeline((c - b) / (decimal)a); //

單位秒

精度為百萬分之一秒。而且由於是long型,所以不存在上面幾個api位數不夠的問題。

未經過超頻等測試,如果是真的,那該api出來的結果就可能不准。

stopwatch 在基礎計時器機制中對計時器的刻度進行計數,從而測量執行時間。如果安裝的硬體和作業系統支援高解析度效能的計數器,則 stopwatch 類將使用該計數器來測量執行時間;否則,stopwatch 類將使用系統計數器來測量執行時間。使用 frequency 和 ishighresolution 兩個靜態字段可以確定實現 stopwatch 計時的精度和解析度。

實際上它裡面就是將queryperformancecounter、queryperformancefrequency兩個win api封裝了一下,如果硬體支援高精度,就呼叫queryperformancecounter,如果不支援就用datetime.ticks來計算。

用法:

stopwatch sw = new

stopwatch();

sw.start();

thread.sleep(

2719

);sw.stop();

console.writeline(sw.elapsedticks / (decimal)stopwatch.frequency);

該方法的原理我不是很明白,硬體知識太匱乏了。精度是ns

在c#中要用該方法必須先建立乙個託管c++專案(因為要內嵌彙編),編譯成dll供c#呼叫,有點麻煩。

c++**:

//

mltimerdot.h

#pragma once

using

namespace

system;

namespace

mltimerdot

//宣告 .net 類

public __gc class

mltimer

//計算時鐘週期

uint64 getcount(void

) };}

c#呼叫:

long a = 0

;queryperformancefrequency(

refa);

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由於呼叫方便,也推薦使用

2014的一點收穫

1.工具類 emacs,git,gtags。1.1 emacs 比較喜歡快捷鍵,尤其像我這種有 儲存強迫症 的人,比vi方便一些。1.2 git 神奇的東西,對我這種公司svn伺服器不好用,又懶得在本機搭伺服器的人,用起來很方便。1.3 gtags 水木上看到的,一用起來果然神奇,果斷拋棄etags...

讀C Primer 一點收穫

以前總是看別人的部落格,且聽說搞it的應該有總結收穫和分享的習慣,於是乎有了寫的衝動。最近剛看完c primer 4th,感覺收穫還是挺多的,借部落格記錄之。看這本書的動機一大半是問了充實自己便於兩年後的找工作。之前對c 的了解完全 於大 一 大2時的課程。從類之後時,就開始一頭霧水了,最多也是課上...

STL的一點收穫(排序)

今天又學到了一點新東西,拿出來大家分享一下,一下內容部分為摘抄。本來在做一道tx14年的面試題,題中需要用到排序,本來想用自帶的快排函式qsort 突然想起stl應該有自己的排序演算法,於是搜了一下,果然有,但是又不了解兩者之間的好壞,大神知道記得說一聲。加標頭檔案algorithm sort預設是...