Yes basically the timing will drift even with mach_time. There are threading 
overheads, plus a priority 1 thread is not hard real-time. There are probably 
other things that will cause the timing to drift by small amounts. Simply not 
being a hard real-time thread will be enough to ensure that the kernel is not 
scheduling accurately.

The only really accurate timers available are either from the CoreAudio 
renderProc or from the frame buffer vsync (CADisplayLink / CVDisplayLink). My 
suggestion would be to use either of those and then ensure that your callback 
does not block, take up too much time, do any memory allocations, or delay the 
renderProc in any way.

If you can live with a slightly less accurate timer I would suggest using GCD 
dispatch_after, it effectively does the same as your code


From: "Mazzaroth M." <[email protected]<mailto:[email protected]>>
Date: Tuesday, 9 December 2014 1:08 pm
To: coreaudio-api 
<[email protected]<mailto:[email protected]>>
Subject: Re: precise timing -- mach_wait_until `drifts`

I should also mention there is a github project here:

https://github.com/mazzaroth/highres-timer

with an iOS demo app.

On Mon, Dec 8, 2014 at 9:07 PM, Mazzaroth M. 
<[email protected]<mailto:[email protected]>> wrote:
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?





 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list      ([email protected])
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/coreaudio-api/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to