Measure elapsed time in Swift
Here's a Swift function I wrote to measure Project Euler problems in Swift
As of Swift 3, there is now a version of Grand Central Dispatch that is "swiftified". So the correct answer is probably to use the DispatchTime API.
My function would look something like:
// Swift 3func evaluateProblem(problemNumber: Int, problemBlock: () -> Int) -> Answer{ print("Evaluating problem \(problemNumber)") let start = DispatchTime.now() // <<<<<<<<<< Start time let myGuess = problemBlock() let end = DispatchTime.now() // <<<<<<<<<< end time let theAnswer = self.checkAnswer(answerNum: "\(problemNumber)", guess: myGuess) let nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds // <<<<< Difference in nano seconds (UInt64) let timeInterval = Double(nanoTime) / 1_000_000_000 // Technically could overflow for long running tests print("Time to evaluate problem \(problemNumber): \(timeInterval) seconds") return theAnswer}
Old answer
For Swift 1 and 2, my function uses NSDate:
// Swift 1func evaluateProblem(problemNumber: Int, problemBlock: () -> Int) -> Answer{ println("Evaluating problem \(problemNumber)") let start = NSDate() // <<<<<<<<<< Start time let myGuess = problemBlock() let end = NSDate() // <<<<<<<<<< end time let theAnswer = self.checkAnswer(answerNum: "\(problemNumber)", guess: myGuess) let timeInterval: Double = end.timeIntervalSinceDate(start) // <<<<< Difference in seconds (double) println("Time to evaluate problem \(problemNumber): \(timeInterval) seconds") return theAnswer}
Note that using NSdate for timing functions is discouraged: "The system time may decrease due to synchronization with external time references or due to an explicit user change of the clock.".
This is a handy timer class based on CoreFoundation
s CFAbsoluteTime
:
import CoreFoundationclass ParkBenchTimer { let startTime:CFAbsoluteTime var endTime:CFAbsoluteTime? init() { startTime = CFAbsoluteTimeGetCurrent() } func stop() -> CFAbsoluteTime { endTime = CFAbsoluteTimeGetCurrent() return duration! } var duration:CFAbsoluteTime? { if let endTime = endTime { return endTime - startTime } else { return nil } }}
You can use it like this:
let timer = ParkBenchTimer()// ... a long runnig task ...println("The task took \(timer.stop()) seconds.")
Use clock
, ProcessInfo.systemUptime
, or DispatchTime
for simple start-up time.
There are, as far as I know, at least ten ways to measure elapsed time:
Monotonic Clock based:
ProcessInfo.systemUptime
.mach_absolute_time
withmach_timebase_info
as mentioned in thisanswer.clock()
in POSIX standard.times()
in POSIX standard. (Too complicated since we needto consider user-time v.s. system-time, and child processes areinvolved.)DispatchTime
(a wrapper around Mach time API) as mentioned by JeremyP in accepted answer.CACurrentMediaTime()
.
Wall Clock based:
(never use those for metrics: see below why)
NSDate
/Date
as mentioned by others.CFAbsoluteTime
as mentioned by others.DispatchWallTime
.gettimeofday()
in POSIX standard.
Option 1, 2 and 3 are elaborated below.
Option 1: Process Info API in Foundation
do { let info = ProcessInfo.processInfo let begin = info.systemUptime // do something let diff = (info.systemUptime - begin)}
where diff:NSTimeInterval
is the elapsed time by seconds.
Option 2: Mach C API
do { var info = mach_timebase_info(numer: 0, denom: 0) mach_timebase_info(&info) let begin = mach_absolute_time() // do something let diff = Double(mach_absolute_time() - begin) * Double(info.numer) / Double(info.denom)}
where diff:Double
is the elapsed time by nano-seconds.
Option 3: POSIX clock API
do { let begin = clock() // do something let diff = Double(clock() - begin) / Double(CLOCKS_PER_SEC)}
where diff:Double
is the elapsed time by seconds.
Why Not Wall-Clock Time for Elapsed Time?
In documentation of CFAbsoluteTimeGetCurrent
:
Repeated calls to this function do not guarantee monotonically increasing results.
Reason is similar to currentTimeMillis
vs nanoTime
in Java:
You can't use the one for the other purpose. The reason is that no computer's clock is perfect; it always drifts and occasionally needs to be corrected. This correction might either happen manually, or in the case of most machines, there's a process that runs and continually issues small corrections to the system clock ("wall clock"). These tend to happen often. Another such correction happens whenever there is a leap second.
Here CFAbsoluteTime
provides wall clock time instead of start-uptime. NSDate
is wall clock time as well.