Measure elapsed time in Swift Measure elapsed time in Swift swift swift

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 CoreFoundations 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:

  1. ProcessInfo.systemUptime.
  2. mach_absolute_time with mach_timebase_info as mentioned in thisanswer.
  3. clock() in POSIX standard.
  4. times() in POSIX standard. (Too complicated since we needto consider user-time v.s. system-time, and child processes areinvolved.)
  5. DispatchTime (a wrapper around Mach time API) as mentioned by JeremyP in accepted answer.
  6. CACurrentMediaTime().

Wall Clock based:

(never use those for metrics: see below why)

  1. NSDate/Date as mentioned by others.
  2. CFAbsoluteTime as mentioned by others.
  3. DispatchWallTime.
  4. 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.