High-precision timer

Hello,


Is there a high-precision timer API in MacOS like that Windows Multimedia Timers provide? I need execute my callback exactly every 1 ms, so I need an API allowing to fire events with this resolution. I can't find appropriate API for this. Ideally I want to use C++.


As far as I know timers with such small intervals are platform-specific, so I suppose MacOS has it.


There are a lot of answers on the web regarding accurate time measurements. But I need accurate timer.

Accepted Reply

Did you investigate the use ofTimer Tolerance ?


Timer Tolerance

In iOS 7 and later and macOS 10.9 and later, you can specify a tolerance for a timer (

tolerance
). This flexibility in when a timer fires improves the system's ability to optimize for increased power savings and responsiveness. The timer may fire at any time between its scheduled fire date and the scheduled fire date plus the tolerance. The timer doesn't fire before the scheduled fire date. For repeating timers, the next fire date is calculated from the original fire date regardless of tolerance applied at individual fire times, to avoid drift. The default value is zero, which means no additional tolerance is applied. The system reserves the right to apply a small amount of tolerance to certain timers regardless of the value of the
tolerance
property.

As the user of the timer, you can determine the appropriate tolerance for a timer. A general rule, set the tolerance to at least 10% of the interval, for a repeating timer. Even a small amount of tolerance has significant positive impact on the power usage of your application. The system may enforce a maximum value for the tolerance.

Replies

Did you investigate the use ofTimer Tolerance ?


Timer Tolerance

In iOS 7 and later and macOS 10.9 and later, you can specify a tolerance for a timer (

tolerance
). This flexibility in when a timer fires improves the system's ability to optimize for increased power savings and responsiveness. The timer may fire at any time between its scheduled fire date and the scheduled fire date plus the tolerance. The timer doesn't fire before the scheduled fire date. For repeating timers, the next fire date is calculated from the original fire date regardless of tolerance applied at individual fire times, to avoid drift. The default value is zero, which means no additional tolerance is applied. The system reserves the right to apply a small amount of tolerance to certain timers regardless of the value of the
tolerance
property.

As the user of the timer, you can determine the appropriate tolerance for a timer. A general rule, set the tolerance to at least 10% of the interval, for a repeating timer. Even a small amount of tolerance has significant positive impact on the power usage of your application. The system may enforce a maximum value for the tolerance.

I saw Timer class and tolerance property but I can't find any information regarding accuracy of this timer. Can I achieve 1 ms resolution with this API?

What I read is that precision is submillisecond… For what it's worth.

Seems it's true. I've performed simple test and accuracy is good enough. But not exactly 1 ms. Sometimes interval jumps to 4 ms. Thank you!

Accurate timing is a complex question. To start, I want to clarify one point. You wrote:

Is there a high-precision timer API in MacOS like that Windows Multimedia Timers provide?

Are you mentioning “Multimedia” simply because that’s the best way to get accurate timers on Windows? Or is your timing related to multimedia stuff, like audio or video recording or playback? This matters because the best timer to use depends on the context. If you’re working with audio, you want the timer to be synchronised with the audio, and thus you need to look at the audio frameworks. Likewise for video. Likewise for 2D and 3D graphics and animations. However, if you’re not working in some special subsystem, you should look to general-purpose timer APIs.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

For high precision, steady timer, I like to use the DispatchSource API.

I use it for precision clocking, or when I need a timer to run during a control drag.

  • There is certainly other smarter ways to update the UI.
  • The leeway also has a minimal value, check the 'DispatchSourceTimer' documentation for all details.
let queue = DispatchQueue(label: "com.myCompany.myApp.timerQueue",
                          qos: .userInteractive,
                          attributes: [],
                          autoreleaseFrequency: .inherit,
                          target: nil)

let timer = DispatchSource.makeTimerSource(flags: .strict, queue: queue)

var counter: Int = 0

timer.schedule(deadline: DispatchTime.now(), 
               repeating: DispatchTimeInterval.nanoseconds(periodInNanoseconds), 
               leeway: DispatchTimeInterval.nanoseconds(1))

timer.setEventHandler {
    // Do something at high rate in the queue
    counter+=1
    if counter % 10000 == 0 {
        DispatchQueue.main.async {
        // Do something in the main queue ( UI Update )
        }
    }
}
        
timer.resume()