How to measure elapsed time to execute a function in Swift

Mykhailo Moiseienko
3 min readMay 24, 2023

--

Time is a critical factor in software development. As developers, we strive to build efficient and responsive applications that deliver exceptional user experiences. One essential aspect of achieving optimal performance is measuring the elapsed time it takes for a function to execute.

Measuring time in seconds

In Swift, we can measure the elapsed time to execute a function using the DispatchTime.

The code sample below demonstrates how we can measure the elapsed time in seconds for a specific operation.

func measureElapsedTime(_ operation: () throws -> Void) throws -> Double {
let startTime = DispatchTime.now()
try operation()
let endTime = DispatchTime.now()

let elapsedTime = endTime.uptimeNanoseconds - startTime.uptimeNanoseconds

return Double(elapsedTime) / 1_000_000_000
}

Measuring time in milliseconds

While measuring elapsed time in seconds can provide a general overview, measuring in milliseconds allows us to dive deeper.

func measureElapsedTime(_ operation: () throws -> Void) throws -> UInt64 {
let startTime = DispatchTime.now()
try operation()
let endTime = DispatchTime.now()

let elapsedTime = endTime.uptimeNanoseconds - startTime.uptimeNanoseconds
let elapsedTimeInMilliSeconds = Double(elapsedTime) / 1_000_000.0

return UInt64(elapsedTimeInMilliSeconds)
}

Usage example

In this example, we have a hypothetical performTimeConsumingOperation function that simulates a time-consuming operation. We want to measure the elapsed time it takes to execute.


// Example function to measure
func performTimeConsumingOperation() {
// Simulating a time-consuming operation
var result = 0
for i in 1...1_000_000 {
result += i
}
print("Result: \(result)")
}

// Usage
do {
let executionTime = try measureElapsedTime(performTimeConsumingOperation)
print("Execution time: \(executionTime) ms")
} catch {
print("An error occurred: \(error)")
}

Measuring average time

In some cases, measuring the average time of function execution can provide more reliable and representative performance measurements. To address this need, we can use the measureAverageTime function presented below. This function allows us to run a given operation multiple times and calculates the average time it takes to execute.

func measureAverageTime(timesToRun: Int = 10, _ operation: () throws -> Void) throws -> UInt64 {
var times = [UInt64]()
for _ in 0..<timesToRun {
let time = try measureElapsedTime(operation)
times.append(time)
}
return times.reduce(0, +) / UInt64(times.count)
}

There are numerous scenarios where measuring the time needed to execute a function can prove to be highly beneficial. Let’s consider a few cases where this knowledge becomes indispensable:

  1. Performance Optimization: As developers, we strive to create fast and efficient applications. Measuring the execution time of specific functions allows us to identify performance bottlenecks and focus our optimization efforts on the areas that need the most attention. By pinpointing the code that takes the most time to execute, we can implement targeted optimizations and ensure our applications run smoothly, delivering a seamless user experience.
  2. Benchmarking and Profiling: When comparing different approaches or algorithms to solve a problem, it’s essential to measure their execution times. By measuring the elapsed time for different implementations, we can objectively evaluate their performance characteristics and make informed decisions about the most efficient solution. Furthermore, in the process of profiling an application, timing-specific functions can help identify areas where optimizations will yield the greatest benefits.
  3. Debugging and Troubleshooting: In complex software systems, identifying the root cause of a performance issue can be a daunting task. By measuring the execution time of individual functions, we can narrow down the search space and identify potentially problematic areas. This knowledge enables us to focus our debugging efforts on the code that contributes the most to the overall execution time, allowing for more effective troubleshooting and quicker resolution of issues.

--

--

Mykhailo Moiseienko
Mykhailo Moiseienko

Written by Mykhailo Moiseienko

📱 Senior iOS Software Engineer. ✍️ Writing about iOS Development, Swift, and SwiftUI.

Responses (1)