Last active
June 26, 2019 12:51
-
-
Save fpillet/1f37d21a2c615bf844d74c179f70759d to your computer and use it in GitHub Desktop.
A tool to measure code performance in Swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There's a typo - 'measure' on line 9. Otherwise looks useful 👍