Skip to content

Instantly share code, notes, and snippets.

@fpillet
Last active June 26, 2019 12:51
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save fpillet/1f37d21a2c615bf844d74c179f70759d to your computer and use it in GitHub Desktop.
Save fpillet/1f37d21a2c615bf844d74c179f70759d to your computer and use it in GitHub Desktop.
A tool to measure code performance in Swift
//
// Created by Florent Pillet on 14/11/16.
// Copyright (c) 2016 Florent Pillet. All rights reserved.
//
import Foundation
/*
* A utility struct that helps mesure the performance of sections of code. Only uses Foundation
* (we could also use QuartzCore's CACurrentMediaTime() for similar precision)
*
* Usage:
*
* MeasurePerf("this code took: ") {
* // code to execute here
* }
*
* Will output:
* this code took 0.12143673s
*
* You can also provide a logging closure for customized logging, or use the default constructor
* and use the time yourself:
*
* let perf = MeasurePerf {
* // code to measure here
* }
*
*/
public struct MeasurePerf {
static let NANOSECONDS_IN_SECOND : UInt64 = 1_000_000_000
static let NANOSECONDS_IN_MILLISECOND : UInt64 = 1_000_000
static let NANOSECONDS_IN_MICROSECOND : UInt64 = 1000
private let startTime = mach_absolute_time()
private(set) var doubleSeconds : Double = 0.0 // a single timing result
private(set) var seconds : UInt64 = 0 // breakdown timing results
private(set) var milliseconds : UInt64 = 0
private(set) var microseconds : UInt64 = 0
private(set) var nanoseconds : UInt64 = 0
init(code: () throws -> Void) rethrows {
defer { computeTime() }
try code()
}
@discardableResult
init(_ message: String, code: () throws -> Void) rethrows {
defer {
computeTime()
print("\(message) \(self.doubleSeconds)s")
}
try code()
}
@discardableResult
init(_ loggingClosure: (UInt64, UInt64, UInt64, UInt64) -> Void, code: () throws -> Void) rethrows {
defer {
computeTime()
loggingClosure(self.seconds, self.milliseconds, self.microseconds, self.nanoseconds)
}
try code()
}
@discardableResult
init(_ loggingClosure: (Double) -> Void, code: () throws -> Void) rethrows {
defer {
computeTime()
loggingClosure(self.doubleSeconds)
}
try code()
}
private mutating func computeTime() {
let endTime = mach_absolute_time()
let elapsed = endTime - startTime
var timeBase = mach_timebase_info_data_t()
mach_timebase_info(&timeBase)
var nanos = elapsed * UInt64(timeBase.numer) / UInt64(timeBase.denom);
seconds = nanos / MeasurePerf.NANOSECONDS_IN_SECOND
nanos = nanos - (seconds * MeasurePerf.NANOSECONDS_IN_SECOND)
milliseconds = nanos / MeasurePerf.NANOSECONDS_IN_MILLISECOND
nanos = nanos - (milliseconds * MeasurePerf.NANOSECONDS_IN_MILLISECOND)
microseconds = nanos / MeasurePerf.NANOSECONDS_IN_MICROSECOND
nanoseconds = nanos - (microseconds * MeasurePerf.NANOSECONDS_IN_MICROSECOND)
doubleSeconds = Double(nanos) / Double(MeasurePerf.NANOSECONDS_IN_SECOND)
}
}
@abargh
Copy link

abargh commented Dec 2, 2016

There's a typo - 'measure' on line 9. Otherwise looks useful 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment