Hi all, I wrote a class that attempts to do precise timing by utilizing mach_wait_until() I keep track of the absolute next_fire_date but despite that I've found that on each iteration it drifts. Is it my implementation or is it something else?
I pass-in the interval, convert it to microseconds, determine the absolute start time, and iterate in a loop. For each loop I increment the next_fire_date by multiplying it by the loop iteration.
- (void)run
{
[[NSThread currentThread] setThreadPriority:1.0];
self.running = YES;
self.abs_start_date = mach_absolute_time();
uint64_t time_to_wait = nanos_to_abs(self.interval * NANOS_PER_MILLISEC);
uint64_t i = 1;
uint64_t next_fire_date = self.abs_start_date + (time_to_wait * i);
NSLog(@"next_fire_date: %llu", next_fire_date);
while (self.running)
{
if (mach_absolute_time() >= next_fire_date)
{
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(highResolutionTimerDidFire)])
{
[self.delegate highResolutionTimerDidFire];
i++;
next_fire_date = self.abs_start_date + (time_to_wait * i);
uint64_t mat = mach_absolute_time();
NSLog(@"next_fire_date - mach_absolute_time = %llu - %llu = %llu | drift: %llu", next_fire_date, mat, next_fire_date - mat, time_to_wait - (next_fire_date - mat));
mach_wait_until(next_fire_date);
}
}
}
}
I can generate precise intervals(next_fire_date), and I mach_wait_until the next_fire_date(last line).
But I've noticed that there is a discrepancy that is always decrementing the accuracy, or drift, from the actual time it should fire.
here is a sample of a log where I fire exactly every second, or every 100000000 nanoseconds. If you look at the timestamp, the beat drifts from .436 to .434 after about a minute. The drift value shows how many nanoseconds were lost on that iteration:
2014-12-08 20:48:35.436 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5263339022368 - 5262339058321 = 999964047 | drift: 35953
2014-12-08 20:48:36.437 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5264339022368 - 5263340106379 = 998915989 | drift: 1084011
2014-12-08 20:48:37.437 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5265339022368 - 5264340106729 = 998915639 | drift: 1084361
2014-12-08 20:48:38.437 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5266339022368 - 5265340106385 = 998915983 | drift: 1084017
2014-12-08 20:48:39.437 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5267339022368 - 5266340101173 = 998921195 | drift: 1078805
2014-12-08 20:48:40.437 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5268339022368 - 5267340052154 = 998970214 | drift: 1029786
...
2014-12-08 20:49:42.434 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5330339022368 - 5329339997208 = 999025160 | drift: 974840
2014-12-08 20:49:43.434 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5331339022368 - 5330340058567 = 998963801 | drift: 1036199
2014-12-08 20:49:44.434 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5332339022368 - 5331340107270 = 998915098 | drift: 1084902
2014-12-08 20:49:45.434 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5333339022368 - 5332340104089 = 998918279 | drift: 1081721
2014-12-08 20:49:46.434 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5334339022368 - 5333340046114 = 998976254 | drift: 1023746
2014-12-08 20:49:47.434 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5335339022368 - 5334340050894 = 998971474 | drift: 1028526
Hopefully this is a clear explanation. Any suggestions?