Search code examples
swifttimensdateelapsedtime

Measure elapsed time in Swift


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

Please have a look at the sample program:

func isPrime(_ 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) {
    print("Prime number")
} else {
    print("NOT a prime number")
}

Solution

  • Update

    With Swift 5.7, everything below becomes obsolete. Swift 5.7 introduces the concept of a Clock which has a function designed to do exactly what is required here.

    There are two concrete examples of a Clock provided: ContinuousClock and SuspendingClock. The former keeps ticking when the system is suspending and the latter does not.

    The following is an example of what to do in Swift 5.7

    func doSomething()
    {
        for i in 0 ..< 1000000
        {
            if (i % 10000 == 0)
            {
                print(i)
            }
        }
    }
    
    let clock = ContinuousClock()
    
    let result = clock.measure(doSomething)
    
    print(result) // On my laptop, prints "0.552065882 seconds"
    
    

    It also allows you to measure closures directly, of course

    let clock = ContinuousClock()
    
    let result = clock.measure {
        for i in 0 ..< 1000000
        {
            if (i % 10000 == 0)
            {
                print(i)
            }
        }
    }
    
    print(result) // "0.534663798 seconds"
    

    Pre Swift 5.7

    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 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
    }
    

    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.".