Last active
September 23, 2019 12:51
-
-
Save Exey/3f58a1c7320d83d66c021a71f350ae11 to your computer and use it in GitHub Desktop.
Benchmark comparing guard vs. if let
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
import Foundation | |
var RUNS = 10 | |
var COUNT = 10_000_000 | |
// Extensions for prints | |
extension Sequence where Element: BinaryFloatingPoint { | |
func average() -> Element { | |
var i: Element = 0 | |
var total: Element = 0 | |
for value in self { | |
total = total + value | |
i += 1 | |
} | |
return total / i | |
} | |
} | |
// Profiler | |
final class Profiler { | |
class func measure(_ closure: (() -> Void)!) -> TimeInterval { | |
let startDate = Date() | |
closure() | |
let endDate = Date() | |
let interval = endDate.timeIntervalSince(startDate) | |
return interval | |
} | |
} | |
// Test Data | |
var testData1: String? = "optional string" | |
var testData2: Int? = 999666 | |
func testFunc(s:String, i:Int) -> Int { | |
return 2+i | |
} | |
// Profilers | |
func testGuard(_ count: Int) -> TimeInterval { | |
return Profiler.measure() { | |
for _ in 1...COUNT { | |
guard let test1 = testData1, let test2 = testData2 else { | |
return | |
} | |
_ = testFunc(s: test1, i: test2) | |
} | |
} | |
} | |
func testIf(_ count: Int) -> TimeInterval { | |
return Profiler.measure() { | |
for _ in 1...COUNT { | |
if let test1 = testData1, let test2 = testData2 { | |
_ = testFunc(s: test1, i: test2) | |
} | |
} | |
} | |
} | |
func warm() { | |
for _ in 1...10_000 { | |
_ = testFunc(s: fastRandomString(Int.random(in: 5...10)), i: Int.random(in: 0...1000)) | |
} | |
} | |
func fastRandomString(_ length: Int)->String{ | |
enum s { | |
static let c = Array("abcdefghjklmnpqrstuvwxyz12345789") | |
static let k = UInt32(c.count) | |
} | |
var result = [Character](repeating: "-", count: length) | |
for i in 0..<length { | |
let r = Int(arc4random_uniform(s.k)) | |
result[i] = s.c[r] | |
} | |
return String(result) | |
} | |
// Results | |
#if arch(i386) || arch(x86_64) | |
print("Device x86_64\n") | |
#elseif arch(arm64) | |
print("Device arm64\n") | |
#else | |
print("Device Unknown\n") | |
#endif | |
// Important Warm | |
print("WARM please wait…\n") | |
warm() | |
// if | |
var results1 = [Double]() | |
for i in 1...RUNS { | |
let t = testIf(COUNT) | |
results1.append(Double(t)) | |
print("#\(i) IF \(t)") | |
} | |
print("IF runs \(RUNS) * \(COUNT) average \(String(describing: results1.average()))") | |
print("") | |
// guard | |
var results2 = [Double]() | |
for i in 1...RUNS { | |
let t = testGuard(COUNT) | |
results2.append(Double(t)) | |
print("#\(i) GUARD \(t)") | |
} | |
print("GUARD runs \(RUNS) * \(COUNT) average \(String(describing: results2.average()))") | |
// total | |
let (resultMin, resultMax) = (min(results1.average(), results2.average()), max(results1.average(), results2.average())) | |
print("\nDIFF \(1.0-resultMin/resultMax)") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment