【问题标题】:Equivalent of gettimeday() for Windows等效于 Windows 的 gettimeday()
【发布时间】:2012-06-09 23:27:37
【问题描述】:

有没有人知道 Windows 环境中 gettimeofday() 函数的等效函数?我正在比较 Linux 和 Windows 中的代码执行时间。我正在使用 MS Visual Studio 2010,它一直说,标识符“gettimeofday”未定义。

【问题讨论】:

标签: visual-studio-2010 winapi


【解决方案1】:

这是一个免费的实现:

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <stdint.h> // portable: uint64_t   MSVC: __int64 

// MSVC defines this in winsock2.h!?
typedef struct timeval {
    long tv_sec;
    long tv_usec;
} timeval;

int gettimeofday(struct timeval * tp, struct timezone * tzp)
{
    // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's
    // This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC)
    // until 00:00:00 January 1, 1970 
    static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL);

    SYSTEMTIME  system_time;
    FILETIME    file_time;
    uint64_t    time;

    GetSystemTime( &system_time );
    SystemTimeToFileTime( &system_time, &file_time );
    time =  ((uint64_t)file_time.dwLowDateTime )      ;
    time += ((uint64_t)file_time.dwHighDateTime) << 32;

    tp->tv_sec  = (long) ((time - EPOCH) / 10000000L);
    tp->tv_usec = (long) (system_time.wMilliseconds * 1000);
    return 0;
}

【讨论】:

  • 非常好。我有一个包含在这个实现中的代码。完全相同,但我需要让这段代码在 Linux 上运行,但我不知道该怎么做。我将如何使用 C++ 或 C 使用相同的实现来实现这段代码以在 Linux 中编译?谢谢
  • @S4nD3r #ifdef _WIN32 ...包括上面的行... #else #include #endif ...查看我在Buddhabrot项目中的用法:raw.githubusercontent.com/Michaelangel007/buddhabrot/master/…
  • 我知道这是旧的,为什么 tzp 传入,因为它没有被引用?
  • @SPlatten 为了与 sys/time.h 二进制兼容: int gettimeofday(struct timeval *tv, struct timezone *tz); int settimeofday(const struct timeval *tv, const struct timezone *tz);
  • @SPlatten tz 永远不应该是 null...只有在使用它的情况下,它发生在 linux 内核中并被指定为已弃用。
【解决方案2】:

GetLocalTime() 表示系统时区的时间,GetSystemTime() 表示 UTC。那些返回SYSTEMTIME 结构中的日期/时间,它被解析为年、月等。如果你想要一个自纪元以来的秒数,请使用SystemTimeToFileTime() 或GetSystemTimeAsFileTime()。 FILETIME 是一个 64 位值,自 1601 年 1 月 1 日 UTC 以来的间隔数为 100ns。

对于间隔,请使用GetTickCount()。它返回自启动以来的毫秒数。

要以最佳分辨率(仅受硬件限制)获取间隔,请使用QueryPerformanceCounter()。

【讨论】:

    【解决方案3】:

    这是使用chrono 的c++11 版本。

    谢谢Howard Hinnant 的建议。

    #if defined(_WIN32)
    #include <chrono>
    
    int gettimeofday(struct timeval* tp, struct timezone* tzp) {
      namespace sc = std::chrono;
      sc::system_clock::duration d = sc::system_clock::now().time_since_epoch();
      sc::seconds s = sc::duration_cast<sc::seconds>(d);
      tp->tv_sec = s.count();
      tp->tv_usec = sc::duration_cast<sc::microseconds>(d - s).count();
    
      return 0;
    }
    
    #endif // _WIN32
    

    【讨论】:

    • 请不要简单地发布代码,解释它的作用以及它如何解决 OPs 问题。
    • 请参阅 stackoverflow.com/a/32763779/576911 了解将 chrono 类型转换为 C 计时 API 类型的更好方法。
    【解决方案4】:

    如果你真的想要一个 Windows gettimeofday() 实现,here is one from PostgreSQL 使用 Windows API 和正确的转换。

    但是,如果您想进行时间编码,我建议您查看 QueryPerformanceCounter() 或 directly invoking the TSC,如果您只打算在 x86 上运行。

    【讨论】:

      【解决方案5】:

      现在我将在 Windows 上使用以下 gettimeofday(),如果为 Windows 8 或更高版本编译,则使用 GetSystemTimePreciseAsFileTime(),否则使用 GetSystemTimeAsFileTime():

      #include <Windows.h>
      struct timezone {
          int tz_minuteswest;
          int tz_dsttime;
      };
      
      int gettimeofday(struct timeval *tv, struct timezone *tz)
      {
          if (tv) {
              FILETIME               filetime; /* 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 00:00 UTC */
              ULARGE_INTEGER         x;
              ULONGLONG              usec;
              static const ULONGLONG epoch_offset_us = 11644473600000000ULL; /* microseconds betweeen Jan 1,1601 and Jan 1,1970 */
      
      #if _WIN32_WINNT >= _WIN32_WINNT_WIN8
              GetSystemTimePreciseAsFileTime(&filetime);
      #else
              GetSystemTimeAsFileTime(&filetime);
      #endif
              x.LowPart =  filetime.dwLowDateTime;
              x.HighPart = filetime.dwHighDateTime;
              usec = x.QuadPart / 10  -  epoch_offset_us;
              tv->tv_sec  = (time_t)(usec / 1000000ULL);
              tv->tv_usec = (long)(usec % 1000000ULL);
          }
          if (tz) {
              TIME_ZONE_INFORMATION timezone;
              GetTimeZoneInformation(&timezone);
              tz->tz_minuteswest = timezone.Bias;
              tz->tz_dsttime = 0;
          }
          return 0;
      }
      

      【讨论】:

        【解决方案6】:

        自 Visual Studio 2015 起,timespec_get 可用:

        #include <inttypes.h>
        #include <stdint.h>
        #include <stdio.h>
        #include <stdlib.h>
        #include <time.h>
        
        static uint64_t
        time_ns(void)
        {
            struct timespec ts;
        
            if (timespec_get(&ts, TIME_UTC) != TIME_UTC)
            {
                fputs("timespec_get failed!", stderr);
                return 0;
            }
            return 1000000000 * ts.tv_sec + ts.tv_nsec;
        }
        
        int main(void)
        {
            printf("%" PRIu64 "\n", time_ns());
            return EXIT_SUCCESS;
        }
        

        使用cl t.c 编译并运行:

        C:\> perl -E "system 't' for 1 .. 10"
        1626610781959535900
        1626610781973206600
        1626610781986049300
        1626610781999977000
        1626610782014814800
        1626610782028317500
        1626610782040880700
        1626610782054217800
        1626610782068346700
        1626610782081375500
        

        【讨论】:

          猜你喜欢
          • 2014-06-20
          • 1970-01-01
          • 2016-01-07
          • 1970-01-01
          • 2015-11-17
          • 2013-10-04
          • 1970-01-01
          • 2014-09-25
          • 1970-01-01
          相关资源
          最近更新 更多