跨平台统一时间函数SDK及用法

前言

    前面讲述过Linux平台下时间统计函数的用法,见linux下时间有关的函数和结构体Linux下时间函数:struct timeval结构体
    本文旨在梳理讲述Windows平台下时间统计函数的使用方法以及跨平台统一时间函数SDK。

1、参考

windows下统计时间的函数
Windows 计算程序运行时间(高精度计时)
Windows 各种计算时间函数总结
Windows下获取当前时间函数汇总
windows/linux 获取本地时间(精确到微妙)

2、Windows平台下时间统计函数使用方法

2.1、方法一:QueryPerformaceCounter()

头文件:#include <windows.h>

  如果需要更高的时间精度(比如说服务器程序的耗时统计),可以在开始计时统计前先调用QueryPerformanceFrequency()函数获得机器内部计时器的时钟频率,接着在需要严格计时的事件发生前和发生之后分别调用QueryPerformanceCounter(),利用两次获得的计数之差和时钟频率,就可以计算出事件经历的精确时间(精度可以达到微秒级别)。

用法如下:

#include <stdio.h>
#include <io.h>
#include <windows.h>   //for GetTickCount function
#include <Mmsystem.h> //for timeGetTime function
#include <time.h>  // for time function
#pragma comment(lib, "Winmm.lib")  //for timeGetTime function


int main()
{
    int  N = 10000;
    double start_t,end_t,cost;
    LARGE_INTEGER begin;
    LARGE_INTEGER end;
    LARGE_INTEGER frequence;
    double duartion;

//     method1:用timeGetTime()来计时,单位为ms
//     DWORD  dwBegin, dwEnd, dwBegin1, dwEnd1;
//     dwBegin = timeGetTime();
//     Sleep(N);
//     dwEnd = timeGetTime();
//     printf("timeGetTime Time: %d\n", dwEnd - dwBegin);

//method2:用GetTickCount()来计时,单位为ms
//     dwBegin1 = GetTickCount();
//     Sleep(N);
//     dwEnd1 = GetTickCount();
//     printf("GetTickCount Time: %d\n", dwEnd - dwBegin);

//method3:用time()来计时,单位为秒
//     time_t begin,end;
//     begin = time(NULL);
//     Sleep(N);
//     end = time(NULL);
//     printf("time: %d\n", end - begin);


//method4:用clock()来计时,单位为ms
//     start_t=clock();  
//     Sleep(10);  
//     end_t=clock();  
//     cost=end_t-start_t;  
//     printf("clock time: %d\n",cost);  

    QueryPerformanceFrequency(&frequence);

    QueryPerformanceCounter(&begin);
    Sleep(1234);
    QueryPerformanceCounter(&end);
    duartion = (double)(end.QuadPart - begin.QuadPart) / (frequence.QuadPart);

    printf("QueryPerformaceCounter time: %1.3f s\n",duartion); //单位为秒,精度为微秒(1000000/cpu主频)

    system("pause");
}

精度分析:精度较高,1微妙

2.2、方法二:clock()

头文件:#include <time.h>

clock()是C/C++中的计时函数,而与其相关的数据类型是clock_t。在MSDN中,查得对clock函数定义如下:

clock_t clock(void) ;

简单而言,就是该程序从启动到函数调用占用CPU的时间。这个函数返回从“开启这个程序进程”到“程序中调用clock()函数”时之间的CPU时钟计时单元(clock tick)数,在MSDN中称之为挂钟时间(wal-clock);若挂钟时间不可取,则返回-1。其中clock_t是用来保存时间的数据类型。

用法如下:

#include <time.h>  
#include <stdio.h>  
int main()  
{  
    double start,end,cost;  
    start=clock();  
    sleep(1);  
    end=clock();  
    cost=end-start;  
    printf("%f\n",cost);  
    return 0;  
}

精度分析: 1ms

2.3、方法三:timeGetTime()

头文件:#include <Mmsystem.h>

引用库:#pragma comment(lib, “Winmm.lib”)

DWORD timeGetTime(VOID);    //毫秒为单位

作用: 返回从系统启动到调用函数时所经过的毫秒数。注意,这个值是32位的,会在0到2^32之间循环,约49.71天。
用法如下:

#include <stdio.h>
#include <windows.h>
#include <Mmsystem.h>
#pragma comment(lib, "Winmm.lib")

int main()
{
    int  N = 3;

    //用timeGetTime()来计时  毫秒
    DWORD  dwBegin, dwEnd;
    dwBegin = timeGetTime();
    Sleep(N);
    dwEnd = timeGetTime();
    printf("%d\n", dwEnd - dwBegin);

    system("pause");
}

精度分析:1ms

2.4、方法四:GetTickCount()

GetTickcount函数:它返回从操作系统启动到当前所经过的毫秒数,它的返回值是DWORD。常常用来判断某个方法执行的时间,其函数原型是:

DWORD GetTickCount(void)

返回值以32位的双字类型DWORD存储,因此可以存储的最大值是(2^32-1) ms约为49.71天,因此若系统运行时间超过49.71天时,这个数就会归0,MSDN中也明确的提到了:”Retrieves the number of milliseconds that have elapsed since the system was started, up to 49.7 days.”。因此,如果是编写服务器端程序,此处一定要万分注意,避免引起意外的状况。

特别注意:这个函数并非实时发送,而是由系统每18ms发送一次,因此其最小精度为18ms。当需要有小于18ms的精度计算时,应使用StopWatch方法进行。

用法如下:

#include <stdio.h>
#include <windows.h>
#include <Mmsystem.h>
#pragma comment(lib, "Winmm.lib")

int main()
{
    int  N = 5;

    //用timeGetTime()来计时  毫秒
    DWORD  dwBegin, dwEnd, dwBegin1, dwEnd1;
    dwBegin = timeGetTime();
    Sleep(N);
    dwEnd = timeGetTime();
    printf("timeGetTime: %d\n", dwEnd - dwBegin);

    dwBegin1 = GetTickCount();
    Sleep(N);
    dwEnd1 = GetTickCount();
    printf("GetTickCount: %d\n", dwEnd - dwBegin);

    system("pause");
}

精度分析: 15~18ms

2.5、方法五:time()

头文件:#include <time.h>

time_t    time(time_t *timer);    //  秒为单位

返回以格林尼治时间(GMT)为标准,从1970年1月1日00:00:00到现在的此时此刻所经过的秒数。

time_t实际是个long长整型typedef long time_t;

用法如下:

#include <stdio.h>
#include <time.h>  // for time function

int main()
{
    int  N = 10000;
//method3:用time()来计时,单位为秒
    time_t begin,end;
    begin = time(NULL);
    Sleep(N);
    end = time(NULL);
    printf("time: %d\n", end - begin);

    system("pause");
}

精度分析: 1s 精度最低

3、补充知识

UTC(世界标准时间),Calendar Time(日历时间),epoch(时间点),clock tick(时钟计时单元)
参考自:Windows下获取当前时间函数汇总

4、跨平台统一时间函数SDK

说明:该SDK可用于Windows平台和Linux平台上的功能函数时间统计。

os_time_sdk.h

#ifndef _OS_TIME_SDK_H_
#define _OS_TIME_SDK_H_

#ifdef __cplusplus
extern "C"{
#endif

#if defined(WIN32) || defined(UNDER_CE) || defined(WIN64)
#include <windows.h>
#include <io.h>
typedef struct _os_timer
{
   LARGE_INTEGER lpFrequency;
   LARGE_INTEGER tStart;
   LARGE_INTEGER tEnd;
}os_timer;

#elif defined(__GNUC__)
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
typedef struct _os_timer
{
  struct timeval tStart;
  struct timeval tEnd;
}os_timer;
#endif

int os_sdk_inittimer(os_timer *pTimer);
int os_sdk_starttimer(os_timer *pTimer);
int os_sdk_stoptimer(os_timer *pTimer);
int os_sdk_sleep(int msecs);
int is_file_exist(char *path);


#ifdef __cplusplus
};
#endif

#endif

os_time_sdk.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include "os_time_sdk.h"


#if defined(WIN32) || defined(UNDER_CE) || defined(WIN64)
int os_sdk_inittimer(os_timer *pTimer)
{
   QueryPerformanceFrequence(&pTimer->lpFrequency);
   return 0;
}

int os_sdk_starttimer(os_timer *pTimer)
{
   QueryPerformanceCounter(&pTimer->tStart);
   return 0;
}

int os_sdk_stoptimer(os_timer *pTimer)
{
   QueryPerformanceCounter(&pTimer->tEnd);
   return (int)((pTimer->tEnd.QuadPart - pTimer->tStart.QuadPart)*1000/(pTimer->lpFrequency.QuadPart));
}
int os_sdk_sleep(int msecs)
{
   Sleep(msecs);
   return 0;
}
int is_file_exist(char *path)
{
   return (_access(path, 0) == -1)? 0 : 1;
}

#elif defined(__GNUC__)
int os_sdk_inittimer(os_timer *pTimer)
{
   return 0;
}
int os_sdk_starttimer(os_timer *pTimer)
{
   gettimeofday(&pTimer->tStart, NULL);
   return 0;
}
int os_sdk_stoptimer(os_timer *pTimer)
{
  gettimeofdayy(&pTimer->tEnd, NULL);
  return (pTimer->tEnd.tv_sec - pTimer->tStart.tv_sec)*1000 + (pTimer->tEnd.tv_usec - pTimer->tStart.tv_usec)/1000;
}
int os_sdk_sleep(int msecs)
{
  usleep(msecs*1000);
  return 0;
}
int is_file_exist(char *path)
{
  return (access(path , 0) == -1) ? 0 : -1;
}
#endif

5、windows/linux 获取本地时间(精确到微妙)

参考自:windows/linux 获取本地时间(精确到微妙)

5.1、windows下获取本地时间的方法

#if defined(WIN32) || defined(UNDER_CE) || defined(WIN64)

#include<time.h>
#include<stdio.h>
#include<string.h>
#include<windows.h>

void getstimeval()
{
        long time;
        SYSTEMTIME sys;
        unsigned int us;
        LARGE_INTEGER tick;
        LARGE_INTEGER timestamp;
        QueryPerformanceFrequency(&tick);
        QueryPerformanceCounter(timestamp);
        us=(timestamp.QuadPart % tick.QuadPart)*1E6/tick.QuadPart;
        GetLocalTime(&sys);

        printf("%04d-%02d-%02d %02d:%02d:%02d.%06d\n",sys.wYear, sys.wMonth, sys.wDay, \
        sys.wHour, sys.wMinute, sys.wSecond, us);
}
#endif

5.2、linux下获取本地时间的方法

#if defined(__GUNC__)

#include<sys/time.h>
#include<time.h>
#include<stdio.h>
#include<string.h>

void getstimeval()
{
        char buf[28];
        struct timeval tv;
        struct tm      tm;
        size_t         len = 28;
        gettimeofday(&tv, NULL);
        localtime_r(&tv.tv_sec, &tm);
        strftime(buf, len, "%Y-%m-%d %H:%M:%S", &tm);
        len = strlen(buf);
        sprintf(buf + len, ".%06.6d", (int)(tv.tv_usec));
        printf("%s\n",buf);
}
#endif

THE END!


本博文只能阅读,谢绝转载,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 2963033731@qq.com

文章标题:跨平台统一时间函数SDK及用法

字数:2k

本文作者:Soaring Lee

发布时间:2019-03-05, 21:45:47

最后更新:2021-08-13, 23:02:32

原始链接:https://soaringleefighting.github.io/2019/03/05/【PE系列】之跨平台统一时间函数SDK及用法/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

×

喜欢就点赞,疼爱就打赏

相册