1

This question has been asked before (see What's the equivalent of Windows' QueryPerformanceCounter on OSX?), but it seems like my needs are a bit different than in other questions, so I'm going to ask again.

All I'm looking for is a tick counter - I don't need UTC or anything like that. And I need a timer that isn't affected by sleep-mode - I need a tick counter that accurately reflects how many ticks have passed, even while the machine was in sleep mode.

QueryPerformanceCounter() on win32 has a number of nice properties that fit my requirements:

  • High resolution, down to microseconds
  • Continues counting, even in system sleep (or rather its count includes time that went by when the system was in sleep mode)
  • Monotonic - never goes down. Not affected by changing the system time.

On OSX, as far as I can tell, I have the following alternatives, and none of them are very good:

  1. gettimeofday()
    • resolution is down to milliseconds (ok, not great)
    • continues counting in system sleep (good)
    • is affected by changing the system clock (bad)
  2. mach_absolute_time()
    • resolution is down to microseconds (good)
    • doesn't count in system sleep (bad)
    • not affected by changing system clock (good)
  3. host_get_clock_service( SYSTEM_CLOCK ) & clock_get_time() (see mach/clock.h)
    • seems to be identical to mach_absolute_time()
  4. host_get_clock_service( CALENDAR_CLOCK ) & clock_get_time() (see mach/clock.h)
    • seems to be identical to gettimeofday()

I don't think that I fully appreciated just how great QueryPerformanceCounter() was until I started looking at this problem. How does it work? Does it use the HPET? Does the HPET go to sleep when the system goes to sleep? If not, why doesn't OSX expose the HPET this way? If so, how does Windows compensate for this?

Update 1:

There's an interesting discussion of how QueryPerformanceCounter works here: http://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx

Apparently it once used CPU TSCs in Win XP days, switched to using the HPET/ACPI timers in Vista, and switched again to improved TSCs in Win 7 but falling back to HPET/ACPI. Still, I was always under the impression that the HPET and TSC didn't survive sleep mode.

Community
  • 1
  • 1
Ted Middleton
  • 6,859
  • 10
  • 51
  • 71
  • 1
    Use `std::chrono`. It's cross-platform. – Rapptz Jul 30 '14 at 00:57
  • http://stackoverflow.com/a/12490414/65863 – Remy Lebeau Jul 30 '14 at 01:07
  • @RemyLebeau: sysctl(KERN_BOOTTIME) returns boot time in seconds. It can't be used as part of a high resolution monotonic counter. See http://stackoverflow.com/questions/15995995/uptime-ios-objective-c-millisecond-precision. – Ted Middleton Jul 30 '14 at 01:11
  • @Rapptz: Sadly, I'm not using C++11. Any idea which timer std::chrono uses on OSX? – Ted Middleton Jul 30 '14 at 01:14
  • @Rapptz: It appears that std::chrono is just using gettimeofday() and mach_absolute_time(). See http://llvm.org/svn/llvm-project/libcxx/trunk/src/chrono.cpp. – Ted Middleton Jul 30 '14 at 01:21
  • @TedMiddleton I'm not sure about the implementation but I know libc++ is typically standard conforming and a `` implementation is supposed to meet all the requirements you've put forth. – Rapptz Jul 30 '14 at 01:26
  • @Rapptz: Just tried std::chrono::steady_clock and std::chrono::high_resolution_clock. Both behave identically to mach_absolute_time(). Which makes sense given that that's how they're implemented. Either the C++11 spec doesn't stipulate sleep behavior for std::chrono, or std::chrono on OSX is out of spec. – Ted Middleton Jul 30 '14 at 01:52
  • @TedMiddleton Well, this works: http://ideone.com/d6iFcW on Linux and Windows. Might be out of spec on Mac OS X. – Rapptz Jul 30 '14 at 01:58

0 Answers0