What should I use to replace gettimeofday() on Windows?

匿名 (未验证) 提交于 2019-12-03 01:08:02

问题:

I'm writing a portable Socket class that supports timeouts for both sending and receiving... To implement these timeouts I'm using select().... But, I sometimes need to know how long I was blocked inside select() which of course on Linux I would implement by calling gettimeofday() before and after I call select() and then using timersub() to calculate the delta...

Given that select() on Windows accepts struct timeval for it's timeout, what method should I used to replace gettimeofday() on Windows?

回答1:

I ended up finding this page: gettimeofday() on windows [edit: link removed because it now points to an advertising site]. Which has a handy, dandy implementation of gettimeofday() on Windows. It uses the GetSystemTimeAsFileTime() method to get an accurate clock.

Update: Here's an active link [edit: link removed because it now points to an advertising site] that points to the implementation the OP referred to. Note also that there's a typo in the linked implementation:

#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)   #define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64 // WRONG #else   #define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL // WRONG #endif 

The values shown are missing an extra 0 at the end (they assumed microseconds, not the number of 100-nanosecond intervals). This typo was found via this comment on a Google code project page. The correct values to use are shown below:

#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)   #define DELTA_EPOCH_IN_MICROSECS  116444736000000000Ui64 // CORRECT #else   #define DELTA_EPOCH_IN_MICROSECS  116444736000000000ULL // CORRECT #endif 

PostgreSQL's implementation of gettimeofday for windows:

/*  * gettimeofday.c  *    Win32 gettimeofday() replacement  *  * src/port/gettimeofday.c  *  * Copyright (c) 2003 SRA, Inc.  * Copyright (c) 2003 SKC, Inc.  *  * Permission to use, copy, modify, and distribute this software and  * its documentation for any purpose, without fee, and without a  * written agreement is hereby granted, provided that the above  * copyright notice and this paragraph and the following two  * paragraphs appear in all copies.  *  * IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING  * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS  * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED  * OF THE POSSIBILITY OF SUCH DAMAGE.  *  * THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR  * A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS  * IS" BASIS, AND THE AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,  * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.  */  #include "c.h"  #include    /* FILETIME of Jan 1 1970 00:00:00. */ static const unsigned __int64 epoch = ((unsigned __int64) 116444736000000000ULL);  /*  * timezone information is stored outside the kernel so tzp isn't used anymore.  *  * Note: this function is not for Win32 high precision timing purpose. See  * elapsed_time().  */ int gettimeofday(struct timeval * tp, struct timezone * tzp) {     FILETIME    file_time;     SYSTEMTIME  system_time;     ULARGE_INTEGER ularge;      GetSystemTime(&system_time);     SystemTimeToFileTime(&system_time, &file_time);     ularge.LowPart = file_time.dwLowDateTime;     ularge.HighPart = file_time.dwHighDateTime;      tp->tv_sec = (long) ((ularge.QuadPart - epoch) / 10000000L);     tp->tv_usec = (long) (system_time.wMilliseconds * 1000);      return 0; } 


回答2:

How about:

unsigned long start = GetTickCount(); // stuff that needs to be timed unsigned long delta = GetTickCount() - start; 

GetTickCount() is not very precise, but will probably work well. If you see a lot of 0, 16 or 31 millisecond intervals, try timing over longer intervals or use a more precise function like timeGetTime.

What I usually do is this:

unsigned long deltastack; int samples = 0; float average;  unsigned long start = GetTickCount(); // stuff that needs to be timed unsigned long delta = GetTickCount() - start;  deltastack += delta; if (samples++ == 10) {    // total time divided by amount of samples    average = (float)deltastack / 10.f;    deltastack = 0;    samples = 0;   } 


回答3:

In your case I would use the platform independent std::clock



回答4:

You can check out QueryPerformanceCounter and QueryPerformanceFrequency. These are very high resolution- down to one tick per ten cycles on some hardware- timers.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!