Timing how long a function takes - ios

I've seen Q/A here about timing function duration in other languages but didn't find anything in Objective-C. If there is one, post the link and I will delete this question
I want to measure the time it takes for some functions to run. I've cobbled together the bits of code below but I wonder if there is a more compact or portable way to do this.
CFTimeInterval startTime = CFAbsoluteTimeGetCurrent();
// do some work
CFTimeInterval difference = CFAbsoluteTimeGetCurrent() - startTime;
printf("elapsed: %f\n", difference)

If you want to precisely time very short timespans there are two additional timing facilities with very low overhead that come to my mind:
mach_absolute_time with nanosecond resolution
__builtin_readcyclecounter: a clang builtin function to read a low-latency, high-accuracy clock.

No,This is the best way using CFAbsoluteTimeGetCurrent();
its Absolute time is measured in seconds relative to the absolute reference date of Jan 1 2001 00:00:00 GMT

Related

(When) Does CACurrentMediaTime/mach_system_time wrap around on iOS?

To get accurate time measurements on iOS, mach_absolute_time() should be used. Or CACurrentMediaTime(), which is based on mach_absolute_time(). This is documented in this Apple Q&A, and also explained in several StackOverflow answers (e.g. https://stackoverflow.com/a/17986909, https://stackoverflow.com/a/30363702).
When does the value returned by mach_absolute_time() wrap around? When does the value returned by CACurrentMediaTime() wrap around? Does this happen in any realistic timespan? The return value of mach_absolute_time() is of type uint64, but I'm unsure about how this maps to a real timespan.
The document you reference notes that mach_absolute_time is CPU dependent, so we can't say how much time must elapse before it wraps. On the simulator, mach_absolute_time is nanoseconds, so if it's wrapping at UInt64.max, that translates to 585 years. On my iPhone 7+, it's 24,000,000 mac_absolute_time per second, which translates to 24 thousand years. Bottom line, the theoretical maximum amount of time captured by mach_absolute_time will vary based upon CPU, but you won't ever encounter this in any practical application.
For what it's worth, consistent with those various posts you found, the CFAbsoluteTimeGetCurrent documentation warns that:
Repeated calls to this function do not guarantee monotonically increasing results. The system time may decrease due to synchronization with external time references or due to an explicit user change of the clock.
So, you definitely don't want to use NSDate/Date or CFAbsoluteTimeGetCurrent if you want accurate elapsed times. Neither ensures monotonically increasing values.
In short, when I need that sort of behavior, I generally use CACurrentMediaTime, because it enjoy the benefits of mach_absolute_time, but it converts it to seconds for me, which makes it very simple to use. And neither it nor mach_absolute_time are going to loop in any realistic time period.

How to correctly format a NSTimeInterval as a time period, respecting i18n?

Given an NSTimeInterval representing a period of time, how do I create a human-readable string that expresses that time period in a way that respects i18N?
For example, if the NSTimeInterval is equal to 10823.23435 seconds, then some reasonable ways of rendering that as a string for those in the US might be:
3:23
3 hours, 23 seconds
etc.
(I.e., stuff you'd see on a stopwatch.)
Presumably other locales might use different renderings.
I'm aware of NSDateFormatter and NSNumberFormatter, but it's not clear to me if or how to use one of these for this problem.
I'm also aware of FormatterKit, but that only does relative time periods (e.g., "3 minutes ago"). I'm looking for absolute time periods.
It is trivial to cook up my own locale-specific solution, but has this problem been solved properly already?
Thanks.
For iOS 8 there are NSDateComponentsFormatter & NSDateIntervalFormatter, they may work for your application.
Docs are lacking see NSHipster: NSFormatter
and
Foundation/NSDateIntervalFormatter.h

Measuring time in microseconds on iOS

I’m trying to get system time in microseconds to measure time between two events. I need to measure at minimum to 1/10th of a millisecond.
I know of NSDate and CFAbsoluteTimeGetCurrent, but both only do milliseconds. Does anyone know of a way I can do this?
CFAbsoluteTimeGetCurrent calls gettimeofday, which has microsecond resolution.
NSDate is simply a wrapper around a CFAbsoluteTime, so it also has microsecond resolution.
Why do you think they only have millisecond resolution?
See mach_absolute_time. It has granularity down to nanoseconds.
http://shiftedbits.org/2008/10/01/mach_absolute_time-on-the-iphone/

iOS prevent date/time update?

a relatively simple question that I've not been able to find a clear answer to. My app is more complex, but answering this question will suffice.
Suppose you're writing a stopwatch app. When the user taps "start", the app stores the current date and time in startTime:
startTime = [NSDate date];
When the user tapes "stop", the app stores the current date and time in stopTime:
stopTime = [NSDate date];
The duration is calculated by:
duration = [stopTime timeIntervalSinceDate:startTime];
and is displayed with something like:
[durationLabel setText:[NSString stringWithFormat:#"%1.2f", duration]];
The typical durations that my app is timing range from 2 to 50 seconds. I need accuracy to 1/100th of a second (e.g. 2.86 seconds).
I'm assuming that there is some protocol that iOS devices use to keep their clocks accurate (cellular or NTP sources?). My concern is that between starting and stopping the stopwatch, the clock on the iOS device is updated which can result in a shift of the current date/time either ahead or back. If this were to happen, the duration calculated would be inaccurate.
I've seen a few posts relating to timing methods for purposes of improving code efficiency. Some suggest using mach_time.h functions, which I'm not familiar with. It's not obvious to me which is the best approach to use.
Is it possible to disable iOS from updating the date & time? Is mach_absolute_time() unaffected by iOS clock updates?
Many thanks!
Tim
You are correct in thinking that CFAbsoluteTime and its derivatives (NSDate dateand so on) are potentially skewed by network updates on 'real' time. Add that to the fact that NSTimer has an accuracy of 50-100ms and you have a timer that is not suited to the most critical of time-sensitive operations.
The answer to this problem seems to be CACurrentMediaTime.
It is a member of the Core Animation group, but there shouldn't be any problem integrating it into non-animation based applications.
CACurrentMediaTime is a wrapper of mach_absolute_time() and makes sense of the "mach absolute time unit," which from my understanding is no fun to tinker with. mach_absolute_time() is calculated by running a non-network synced timer since the device was last booted.
There is relatively little information on CACurrentMediaTime but here are some sources and further reading:
Apple's sparse documentation of CACurrentMediaTime
Stack Overflow - NSTimer vs CACurrentMediaTime()
http://bendodsonapps.com/weblog/2013/01/29/ca-current-media-time/
http://blog.spacemanlabs.com/2011/09/all-in-the-timing-keeping-track-of-time-passed-on-ios/
http://forum.sparrow-framework.org/topic/accurate-timer
Note: If you do use CACurrentMediaTime, make sure you include and link the QuartzCore.framework
Check out this here. I would say forget about the current time check and use a precision timer since it won't rely on the current time but instead uses an interval.

How can I measure the time it takes between two lines of code in Objective-C for iOS?

I have the following code that is taking a while to process:
self.itemsArray = [Helper changeTheA:self.itemsArray];
self.itemsArray = [Helper convertDates:self.itemsArray];
Is there a way, in Instruments or somewhere else, that I can measure the time is takes to go from the first line of code to the second line of code.... in ticks or milliseconds or something?
I want to do some tweaking but I need to be able to measure in order to see if I'm making an improvement over the previous code.
Quickest, dirtiest, possibly not very precise way
NSDate *startDate = [NSDate date];
self.itemsArray = [Helper changeTheA:self.itemsArray];
NSLog(#"changeTheA time taken: %f", -[startDate timeIntervalSinceNow]);
A slightly more involved but probably more useful solution, if you are doing some basic profiling can be seen here, it uses a C function that executes a block you provide.
Big side note
As Justin points out the actual act of creating an NSDate and then logging it out will introduce interference to your measurements and so this technique is only really any good for getting ball park figures and even then you should probably run large amounts of iterations of your code within the timing block. If you require accurate measurements then skip to Justin's answer
Yes. You would use Instruments' Sampler for this.
Run the app, exercise the program for a while, then locate the symbol in Instruments which contains:
self.itemsArray = [Helper changeTheA:self.itemsArray];
self.itemsArray = [Helper convertDates:self.itemsArray];
It should show the weights line by line. Also note that Instruments allows you to specify the sampling frequency, down to 40 microseconds.
I would use the following code:
NSTimeInterval start = CACurrentMediaTime();
// your code goes here
NSTimeInterval end = CACurrentMediaTime();
NSTimeInterval delta = end - start;
NSLog(#"Execution took %f seconds.", delta);
It is a lot more precise than NSDate.

Resources