delphi 函数如下:
//取系统时间,类似于 GetTickCount ,但精确度高,精确到1ms。且取出时间为8个字节整型
class function TSwitchMacList.getSysTickCount64() : int64;
{$j+} //局部静态变量
const
TicksPerSecond : int64 = 0;
{$j-}
var
Tick,Seconds,LeftPart,MillSeconds,Ret : int64;
begin
if TicksPerSecond = 0 then QueryPerformanceFrequency(TicksPerSecond);
QueryPerformanceCounter(Tick);
Seconds := Tick div TicksPerSecond;
LeftPart := Tick - (TicksPerSecond*Seconds);
MillSeconds := LeftPart*1000 div TicksPerSecond;
Ret := Seconds*1000+MillSeconds;
result := Ret;
end;
C函数如下:
__int64 GetSysTickCount64()
{
static LARGE_INTEGER TicksPerSecond = {0};
LARGE_INTEGER Tick;
if(!TicksPerSecond.QuadPart)
{
QueryPerformanceFrequency(&TicksPerSecond);
}
QueryPerformanceCounter(&Tick);
__int64 Seconds = Tick.QuadPart/TicksPerSecond.QuadPart;
__int64 LeftPart = Tick.QuadPart - (TicksPerSecond.QuadPart*Seconds);
__int64 MillSeconds = LeftPart*1000/TicksPerSecond.QuadPart;
__int64 Ret = Seconds*1000+MillSeconds;
// __ASSERT(Ret>0);
return Ret;
};
源贴地址:
http://huyuguang1976.spaces.live.com/blog/cns!2A9E272E3C33AFF1!182.entry
源贴内容:
高精度 GetTickCount64
32位的GetTickCount有2个缺陷,第一是49天之后uint32就不够用了,这对于运行于长时间不关机的服务器,或者总是处于休眠模式下的笔记本上的程序来说,是无法忍受的缺陷。其次是GetTickCount的精度有限,MSDN文档中叙述说精度取决于系统timer,一般来说,NT家族的操作系统的系统timer是10ms或20ms。
vista支持一个新的函数叫GetTickCount64,这个函数返回int64的毫秒数,从而避开了49天之后uint32不够用的问题。但这个函数仅能在vista或者win2k8上使用。
为此,写一个自己的高精度函数是有必要的。
第一版代码如下:
int64 HELPER_API GetSysTickCount64()
{
static LARGE_INTEGER TicksPerSecond = {0};
LARGE_INTEGER Tick;
if(!TicksPerSecond.QuadPart)
{
QueryPerformanceFrequency(&TicksPerSecond);
}
QueryPerformanceCounter(&Tick);
return Tick.QuadPart *1000/TicksPerSecond.QuadPart;
}
这个函数逻辑很简单,首先获取每秒cpu的时钟周期数,然后获取开机以来cpu的时钟数,然后一除即可得到开机以来的毫秒数。
但这个函数有一个隐秘的错误在于,Tick.QuadPart*1000有可能导致int64溢出,实际上在我的一台运行了不到100天的服务器上的确发生了这种事情。cpu越来越快,服务器越来越稳定,从而Tick的值非常大,再乘以1000,溢出也就不奇怪了。
因此第二版代码如下:
int64 HELPER_API GetSysTickCount64()
{
static LARGE_INTEGER TicksPerSecond = {0};
LARGE_INTEGER Tick;
if(!TicksPerSecond.QuadPart)
{
QueryPerformanceFrequency(&TicksPerSecond);
}
QueryPerformanceCounter(&Tick);
int64 Seconds = Tick.QuadPart/TicksPerSecond.QuadPart;
int64 LeftPart = Tick.QuadPart - (TicksPerSecond.QuadPart*Seconds);
int64 MillSeconds = LeftPart*1000/TicksPerSecond.QuadPart;
int64 Ret = Seconds*1000+MillSeconds;
_ASSERT(Ret>0);
return Ret;
}