what is the granularity of the iPhone 4S timer? - iphone

Since the iPhone4S is reported to have a 800MHz clock , it might be that the timer has a 200MHz (5nsec) granularity? Anyone know what the shortest loop period might be?

From the NSTimer reference page:
Because of the various input sources a typical run loop manages, the
effective resolution of the time interval for a timer is limited to on
the order of 50-100 milliseconds. If a timer’s firing time occurs
during a long callout or while the run loop is in a mode that is not
monitoring the timer, the timer does not fire until the next time the
run loop checks the timer. Therefore, the actual time at which the
timer fires potentially can be a significant period of time after the
scheduled firing time.
Again, though, that's for NSTimer, which you generally use for triggering events that should happen at certain times or time intervals. If you're trying to measure elapsed time you can likely get a much more accurate result than 100ms, but I don't see a documented accuracy in the docs.

Try including mach/mach_time.h, mach_time() seems to provide microsecond resolution timing vales or better, and doesn't have non-monotonicity problems as NSDate does.

Related

Millisecond timer?

Does anyone know how to make a timer with a time interval of 0.001? I read somewhere that a Timer can't have a time interval lower than 0.02, and my timer is behaving that way.
My timer:
timer = Timer.scheduledTimer(timeInterval: 0.001, target: self, selector: #selector(self.updateTimer), userInfo: nil, repeats: true)
#objc func updateTimer() {
miliseconds += 0.001
}
Yes, you can have time intervals less than 0.02 seconds. E.g. 0.01 second interval is easily accomplished. But at 0.001 or 0.0001 seconds, you’re starting to be constrained by practical considerations of how much you could accomplish in that period of time.
But if your goal is to represent something in the UI, there’s rarely any point for exceeding the device’s maximum frames per second (usually 60 fps). If the screen can only be updated every 60th of a second, what’s the point in calculating more frequently than that? That’s just wasted CPU cycles. By the way, if we were trying to achieve optimal screen refresh rates, we’d use CADisplayLink, not Timer. It works just like a timer, but is optimally timed for refreshing the screen at its optimal rate.
For what it’s worth, the idea of updating milliseconds to capture elapsed time is a bit of non-starter. We never update a “elapsed time counter” like this, because even in the best case scenarios, the frequency is not guaranteed. (And because of limitations in binary representations of fractional decimal values, we rarely want to be adding up floating point values like this, either.)
Instead, if we want to have the fastest possible updates in our UI, we’d save the start time, start a CADisplayLink, and every time the timer handler is called, calculate the elapsed time as the difference between current time and the start time.
Now, if you really needed a very precise timer, it can be done, but you should see Technical Note TN2169, which shows how to create high precision timer. But this is more of an edge-case scenario.
Short answer: You can't do that. On iOS and Mac OS, Timers are invoked by your app's run loop, and only get invoked when your app visits the main event loop. How often a short-interval timer actually fires will depend on how much time your app spends serving the event loop. As you say, the docs recommend a minimum interval of about 1/50th of a second.
You might look at using a CADisplayLink timer, which is tied to the display refresh. Those timers need to run fast in order to not interfere with the operation of your app.
Why do you think you need a timer that fires exactly every millisecond?

Will having two NSTimers in one class cause them to be less accurate?

I have one NSTimer which is my main game loop, it calls 60 times a second. I have another timer which is a countdown, which gets called 0.001 times a second. Is it normal that timer is not accurate? or should i call the countdown timer fewer times per second?
NSTimers are not accurate. The time interval you specify is simply a goal. The NSTimer will try to hit that goal but the more stuff you have running on that thread the slower the cycle time will be. Your 0.001 timer is probably going way too fast to be useful and will suffer from accuracy problems. If you need real time accuracy you will have to track what time the timer is actually firing with an NSDate and compensate accordingly.
If I'm reading your question correctly the second timer (which I assume is fired every 0.001) seconds is not going to be accurate.
NSTimer has a resolution of about 50-100 milliseconds (0.05s-0.1s) and this can be significantly impacted if your run loop is loaded.

Using XCode and instruments to improve iPhone app performance

I've been experimenting with Instruments off and on for a while and and I still can't do the following (with any sensible results): determine or estimate the average runtime of a function that's called many times.
For example if I'm driving my gameLoop at 60 Hz with a CADisplayLink I'd like to see how long the loop takes to run on average... 10 ms? 30 ms etc.
I've come close with the "CPU activity" instrument but the results are inconsistent or don't make sense. The time profiler seems promising but all I can get is "% of runtime"... and I'd like an actual runtime.
I'm not sure instruments is your best bet here. Instruments samples your code, meaning (amongst other things) that it affects timing. If you want to know how long a loop takes then you should put something in the code to calculate and either retain or display the amount of time each loop is taking.
An actual runtime can be had by:
// activity starts
NSDate* startTime = [NSDate date];
// activity ends
NSLog(#"time elapsed this loop is %f", fabs([startTime timeIntervalSinceNow]));
Getting an average is easy if you have a time calculated per loop since you can sum the times, count the loops and divide before you display the average.
Anything in your loop affects the timing, of course, but this affects in a minimal way.
You should try using Shark for the time profiling of which you speak.
I've tried Time Profiler but it doesn't give you an average or total run time for a method. It just tells you how much time your code is spending in a method during your recording. It tells you your code spends a lot of time in a method but doesn't tell you whether that's because that method ran once and took a long time or whether that method was called many times but ran real fast. If its the former then you should concentrate on making the method faster. If it's the latter you should have your code call the method less often. You have to figure out which it is yourself. Making things more difficult is the Run Loop which has input sources that fire off events like the timer service or I/O. These get passed to handlers which could be Apple's. If one of Apple's handlers is taking a long time then Time Profiler shows it as a hot spot but unless you know what that handler is doing and why there's not much you can do about it. Apple's stuff is not even necessarily called anywhere from your end of the call stack so you can't optimize very easily. I've had more success with OpenGL ES Analyzer as its API Statistics gives you call count, total time, and average time for OpenGL ES calls. Doesn't help you if you aren't doing OpenGL ES.

What is the fastest I should run an NSTimer?

What is the fastest I can run an NSTimer and still get reliable results? I've read that approaching 30ms it STARTS to become useless, so where does it "start to start becoming useless"...40ms? 50ms?
Say the docs:
the effective resolution of the time
interval for a timer is limited to on
the order of 50-100 milliseconds
Sounds like if you want to be safe, you shouldn't use timers below 0.1 sec. But why not try it in your own app and see how low you can go?
You won't find a guarantee on this. NSTimers are opportunistic by nature since they run with the event loop, and their effective finest granularity will depend on everything else going on in your app in addition to the limits of whatever the Cocoa timer dispatch mechanisms are.
What's you definition of reliable? A 16 mS error in a 1 second timer is under 2% error, but in a 30 mS timer is over 50% error.
NSTimers will wait for whatever is happening in the current run loop to finish, and any errors in time can accumulate. e.g. if you touch the display N times, all subsequent repeating NSTimer firings may be late by the cumulative time taken by 0 to N touch handlers (plus anything else that was running at the "wrong" time). etc.
CADisplayLink timers will attempt to quantize time to the frame rate, assuming that no set of foreground tasks takes as long as a frame time.
Depends on what kind of results you are trying to accomplish. NSTimer Class 0.5 - 1.0 is a good place to start for reliable results.

Most likely to be on-time: +timeWithTimeInterval or -performSelector:withObject:afterDelay:

I would like to play a sound for only a short span of time, shorter than the duration of the sound file. Therefore, at the same time as I start playing, I would like to queue up a task that will stop the sound.
I see two choices for queuing up the stop method: NSTimer and performSelector:withObject:afterDelay:
Does anyone know which of the two is most likely to trigger on time, or have a higher priority? It is not imperative that I get called with millisecond accuracy, but accuracy to 0.1 second would be great.
Addendum: Does anyone know where I could find documentation on the priority of different timer and delay tasks? For example, how would the below rank:
NSTimer tasks
performSelector
the calling of a view's drawRect after setNeedsDisplay has been called
the calling of a layer's drawing routines after setNeedsDisplay has been called
any other delayed tasks
And would it be useful to try to do this in a different thread?
performSelector:withObject:afterDelay: will create a timer to know when to fire so both approaches should be equally (un-)reliable. If your code performs an expensive calculation on the main thread and doesn't return control to the run loop or if the run loop has to process lots of events, the timer won't fire on time.
Have a NSTimer, but with a much smaller time interval than the one that your sound has to play. When your timer fires, and that is a couple of times while your sound plays, you would count how much time has passed since you started it. When that time exceeds a margin set by you, you stop the sound.
From my understanding, they should be pretty much the same. However, the best way to figure this out is to test it yourself. Run a bunch of tests and record the exact time, then see which is closer.