Swift Elapsed Time Measurement

How can we measure the time taken to launch a function in Swift? I am trying to display the elapsed time as follows: "Elapsed time is 0.05 seconds." Saw that in Java we can use System.nanoTime (), are there any equivalent methods available in Swift for this?

Please look at an example program:

func isPrime(var number:Int) ->Bool { var i = 0; for i=2; i<number; i++ { if(number % i == 0 && i != 0) { return false; } } return true; } var number = 5915587277; if(isPrime(number)) { println("Prime number"); } else { println("NOT a prime number"); } 
+100
time swift nsdate elapsedtime
Jul 15 '14 at 10:14
source share
17 answers

Here is the Swift function I wrote to measure Project Euler tasks in Swift

As for Swift 3, now there is a version of Grand Central Dispatch, which is β€œsmoothed”. So the correct answer is probably to use the DispatchTime API .

My function will look something like this:

 // Swift 3 func 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 1 func 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 } 

Please note that using NSdate for synchronization functions is not recommended: "System time may be reduced due to synchronization with external time references or due to an explicit change of clock by the user."

+184
Jul 15 '14 at 10:35
source share

This is a convenient timer class based on CoreFoundation CFAbsoluteTime :

 import CoreFoundation class 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 as follows:

 let timer = ParkBenchTimer() // ... a long runnig task ... println("The task took \(timer.stop()) seconds.") 
+64
Oct 26 '14 at 21:30
source share

Use clock , ProcessInfo.systemUptime or DispatchTime for a simple start time.




As far as I know, there are at least ten ways to measure elapsed time:

Monotone watches based on:

  1. ProcessInfo.systemUptime .
  2. mach_absolute_time with mach_timebase_info as mentioned in this answer .
  3. clock() in the POSIX standard .
  4. times() in the POSIX standard . (Too complicated, since we need to consider user time versus system time, and child processes are involved.)
  5. DispatchTime (wrapper around the Mach time API), as mentioned by JeremyP in the accepted answer.
  6. CACurrentMediaTime() .

Wall clock based on:

(never use them for metrics: see below why)

  1. NSDate / Date as mentioned by others.
  2. CFAbsoluteTime as mentioned by others.
  3. DispatchWallTime .
  4. gettimeofday() in the POSIX standard .



Options 1, 2, and 3 are described in detail below.

Option 1: Base Information Processing API

 do { let info = ProcessInfo.processInfo let begin = info.systemUptime // do something let diff = (info.systemUptime - begin) } 

where diff:NSTimeInterval is the elapsed time in 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 for 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 in seconds.

Why not a wall clock in the past?

In the CFAbsoluteTimeGetCurrent documentation:

Repeated calls to this function do not guarantee monotonically increasing results.

The reason is similar to currentTimeMillis vs nanoTime in Java :

You cannot use one for another purpose. The reason is that no computer clock is perfect; it always drifts and sometimes needs to be fixed. This correction can occur either manually, or in the case of most machines, there is a process that runs and constantly issues small corrections to the system clock ("wall clock"). This often happens. Another such correction occurs whenever there is a leap second.

Here CFAbsoluteTime provides the wall clock time instead of the start time. NSDate is the wall clock time.

+41
May 26 '16 at 2:44
source share

Swift 4 shortest answer:

 let startingPoint = Date() // ... intensive task print("\(startingPoint.timeIntervalSinceNow * -1) seconds elapsed") 

It will give you something around 1.02107906341553 seconds (the time, of course, will vary depending on the task, I just show it for you guys to see the decimal precision level for this measurement).

Hope this helps someone in Swift 4 from now on!

+23
Feb 07 '18 at 22:28
source share
 let start = NSDate() for index in 1...10000 { // do nothing } let elapsed = start.timeIntervalSinceNow // elapsed is a negative value. 
+13
Jun 22 '15 at 9:03
source share

You can create a time function to measure your calls. I am inspired by Klaas answer.

 func time <A> (f: @autoclosure () -> A) -> (result:A, duration: String) { let startTime = CFAbsoluteTimeGetCurrent() let result = f() let endTime = CFAbsoluteTimeGetCurrent() return (result, "Elapsed time is \(endTime - startTime) seconds.") } 

This function allows you to call it like this: time (isPrime(7)) , which returns a tuple containing the result, and a string description of elapsed time.

If you want only the time elapsed through this time, you can do it time (isPrime(7)).duration

+6
Jan 16 '15 at 18:34
source share

Simple helper function for measuring runtime with closure.

 func printExecutionTime(withTag tag: String, of closure: () -> ()) { let start = CACurrentMediaTime() closure() print("#\(tag) - execution took \(CACurrentMediaTime() - start) seconds") } 

Application:

 printExecutionTime(withTag: "Init") { // Do your work here } 

Result: #Init - execution took 1.00104497105349 seconds

+3
Dec 13 '17 at 17:07
source share

you can measure nanoseconds, for example, for example. this is:

 let startDate: NSDate = NSDate() // your long procedure let endDate: NSDate = NSDate() let dateComponents: NSDateComponents = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian).components(NSCalendarUnit.CalendarUnitNanosecond, fromDate: startDate, toDate: endDate, options: NSCalendarOptions(0)) println("runtime is nanosecs : \(dateComponents.nanosecond)") 
+2
Jul 15 '14 at 10:35
source share

I use this:

 public class Stopwatch { public init() { } private var start_: NSTimeInterval = 0.0; private var end_: NSTimeInterval = 0.0; public func start() { start_ = NSDate().timeIntervalSince1970; } public func stop() { end_ = NSDate().timeIntervalSince1970; } public func durationSeconds() -> NSTimeInterval { return end_ - start_; } } 

I do not know if it was more or less accurate than the previous ones. But seconds have many decimals and seem to catch small code changes in algorithms like QuickSort using swap () versus swap urself implementation, etc.

Do not forget to check the effectiveness of the assembly when testing performance:

Swift compiler optimizations

+2
Jun 19 '15 at 19:33
source share

Here is my attempt at the simplest answer:

 let startTime = Date().timeIntervalSince1970 // 1512538946.5705 seconds // time passes (about 10 seconds) let endTime = Date().timeIntervalSince1970 // 1512538956.57195 seconds let elapsedTime = endTime - startTime // 10.0014500617981 seconds 

Notes

  • startTime and endTime are of type TimeInterval , which is just typealias for Double , so it's easy to convert it to Int or whatever. Time is measured in seconds to the nearest millisecond.
  • See also DateInterval , which includes the actual start and end times.
  • Using time since 1970 is like Java timestamps .
+2
Dec 6 '17 at 5:12
source share

I borrowed an idea from Klaas to create a lightweight structure for measuring runtime and interval:

Code Usage:

 var timer = RunningTimer.init() // Code to be timed print("Running: \(timer) ") // Gives time interval // Second code to be timed print("Running: \(timer) ") // Gives final time 

The stop function should not be called, since the print function will give time elapsed. It can be called repeatedly to get time. But to stop the timer at a certain point in the timer.stop() code, it can also be used to return the time in seconds: let seconds = timer.stop() After the timer is stopped, the timer interval will not be there, so print("Running: \(timer) ") will give the correct time even after a few lines of code.

Below is the code for RunningTimer. It is tested for Swift 2.1:

 import CoreFoundation // Usage: var timer = RunningTimer.init() // Start: timer.start() to restart the timer // Stop: timer.stop() returns the time and stops the timer // Duration: timer.duration returns the time // May also be used with print(" \(timer) ") struct RunningTimer: CustomStringConvertible { var begin:CFAbsoluteTime var end:CFAbsoluteTime init() { begin = CFAbsoluteTimeGetCurrent() end = 0 } mutating func start() { begin = CFAbsoluteTimeGetCurrent() end = 0 } mutating func stop() -> Double { if (end == 0) { end = CFAbsoluteTimeGetCurrent() } return Double(end - begin) } var duration:CFAbsoluteTime { get { if (end == 0) { return CFAbsoluteTimeGetCurrent() - begin } else { return end - begin } } } var description:String { let time = duration if (time > 100) {return " \(time/60) min"} else if (time < 1e-6) {return " \(time*1e9) ns"} else if (time < 1e-3) {return " \(time*1e6) Β΅s"} else if (time < 1) {return " \(time*1000) ms"} else {return " \(time) s"} } } 
+1
Dec 16 '15 at 10:00
source share

Wrap it in a completion block for ease of use.

 public class func secElapsed(completion: () -> Void) { let startDate: NSDate = NSDate() completion() let endDate: NSDate = NSDate() let timeInterval: Double = endDate.timeIntervalSinceDate(startDate) println("seconds: \(timeInterval)") } 
+1
Mar 08 '16 at 6:37
source share

Just copy and paste this feature. Written in swift 5. Copy JeremyP here.

 func calculateTime(block : (() -> Void)) { let start = DispatchTime.now() block() let end = DispatchTime.now() let nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds let timeInterval = Double(nanoTime) / 1_000_000_000 print("Time: \(timeInterval) seconds") } 

Use it as

 calculateTime { exampleFunc()// function whose execution time to be calculated } 
+1
May 30 '19 at 16:16
source share

This is a snippet that I came up with and it seems to work on my Macbook with Swift 4.

I have never tested it on other systems, but I thought it was worth sharing this anyway.

 typealias MonotonicTS = UInt64 let monotonic_now: () -> MonotonicTS = mach_absolute_time let time_numer: UInt64 let time_denom: UInt64 do { var time_info = mach_timebase_info(numer: 0, denom: 0) mach_timebase_info(&time_info) time_numer = UInt64(time_info.numer) time_denom = UInt64(time_info.denom) } // returns time interval in seconds func monotonic_diff(from: MonotonicTS, to: MonotonicTS) -> TimeInterval { let diff = (to - from) let nanos = Double(diff * time_numer / time_denom) return nanos / 1_000_000_000 } func seconds_elapsed(since: MonotonicTS) -> TimeInterval { return monotonic_diff(from: since, to:monotonic_now()) } 

Here is an example of how to use it:

 let t1 = monotonic_now() // .. some code to run .. let elapsed = seconds_elapsed(since: t1) print("Time elapsed: \(elapsed*1000)ms") 

Another way is to do it more explicitly:

 let t1 = monotonic_now() // .. some code to run .. let t2 = monotonic_now() let elapsed = monotonic_diff(from: t1, to: t2) print("Time elapsed: \(elapsed*1000)ms") 
0
Mar 25 '18 at 12:32
source share

This is how I wrote it.

  func measure<T>(task: () -> T) -> Double { let startTime = CFAbsoluteTimeGetCurrent() task() let endTime = CFAbsoluteTimeGetCurrent() let result = endTime - startTime return result } 

To measure an algorithm, use it like this.

 let time = measure { var array = [2,4,5,2,5,7,3,123,213,12] array.sorted() } print("Block is running \(time) seconds.") 
0
Apr 02 '18 at 23:45
source share

Swift3 static class for synchronizing core functions. It will track each timer by name. Call it the way you want to start measuring:

 Stopwatch.start(name: "PhotoCapture") 

Call to record and print the elapsed time:

 Stopwatch.timeElapsed(name: "PhotoCapture") 

This output is: *** PhotoCapture has expired ms: 1402.415125 There is a "useNanos" parameter if you want to use nanos. Please feel free to change as necessary.

  class Stopwatch: NSObject { private static var watches = [String:TimeInterval]() private static func intervalFromMachTime(time: TimeInterval, useNanos: Bool) -> TimeInterval { var info = mach_timebase_info() guard mach_timebase_info(&info) == KERN_SUCCESS else { return -1 } let currentTime = mach_absolute_time() let nanos = currentTime * UInt64(info.numer) / UInt64(info.denom) if useNanos { return (TimeInterval(nanos) - time) } else { return (TimeInterval(nanos) - time) / TimeInterval(NSEC_PER_MSEC) } } static func start(name: String) { var info = mach_timebase_info() guard mach_timebase_info(&info) == KERN_SUCCESS else { return } let currentTime = mach_absolute_time() let nanos = currentTime * UInt64(info.numer) / UInt64(info.denom) watches[name] = TimeInterval(nanos) } static func timeElapsed(name: String) { return timeElapsed(name: name, useNanos: false) } static func timeElapsed(name: String, useNanos: Bool) { if let start = watches[name] { let unit = useNanos ? "nanos" : "ms" print("*** \(name) elapsed \(unit): \(intervalFromMachTime(time: start, useNanos: useNanos))") } } 

}

0
May 17 '18 at 16:35
source share

Based on Franklin Yu's answer and Ker's comments

the details

  • Xcode 10.1 (10B61)
  • Swift 4.2

Solution 1

measurement (_ :)

Decision 2

 import Foundation class Measurer<T: Numeric> { private let startClosure: ()->(T) private let endClosure: (_ beginningTime: T)->(T) init (startClosure: @escaping ()->(T), endClosure: @escaping (_ beginningTime: T)->(T)) { self.startClosure = startClosure self.endClosure = endClosure } init (getCurrentTimeClosure: @escaping ()->(T)) { startClosure = getCurrentTimeClosure endClosure = { beginningTime in return getCurrentTimeClosure() - beginningTime } } func measure(closure: ()->()) -> T { let value = startClosure() closure() return endClosure(value) } } 

Using Solution 2

 // Sample with ProcessInfo class m = Measurer { ProcessInfo.processInfo.systemUptime } time = m.measure { _ = (1...1000).map{_ in Int(arc4random()%100)} } print("ProcessInfo: \(time)") // Sample with Posix clock API m = Measurer(startClosure: {Double(clock())}) { (Double(clock()) - $0 ) / Double(CLOCKS_PER_SEC) } time = m.measure { _ = (1...1000).map{_ in Int(arc4random()%100)} } print("POSIX: \(time)") 
0
Jun 26 '18 at 14:32
source share



All Articles