Timing the difference between protocols and protocol-constrained generics
import Darwin | |
import CoreFoundation.CFDate | |
protocol NumberGeneratorType { | |
mutating func generateNumber() -> Int | |
} | |
struct RandomGenerator: NumberGeneratorType { | |
func generateNumber() -> Int { | |
return Int(arc4random_uniform(10)) | |
} | |
} | |
struct IncrementingGenerator: NumberGeneratorType { | |
var n: Int | |
init(start: Int) { n = start } | |
mutating func generateNumber() -> Int { | |
n += 1 | |
return n | |
} | |
} | |
struct ConstantGenerator: NumberGeneratorType { | |
let n: Int | |
init(constant: Int) { n = constant } | |
func generateNumber() -> Int { | |
return n | |
} | |
} | |
func generateUsingProtocol(var g: NumberGeneratorType, count: Int) -> Int { | |
return reduce(stride(from: 0, to: count, by: 1), 0) { total, _ in | |
total &+ g.generateNumber() | |
} | |
} | |
func generateUsingGeneric<T: NumberGeneratorType>(var g: T, count: Int) -> Int { | |
return reduce(stride(from: 0, to: count, by: 1), 0) { total, _ in | |
total &+ g.generateNumber() | |
} | |
} | |
extension String { | |
func lpad(#to: Int, with: Character) -> String { | |
let pad = to - count(self) | |
return pad > 0 | |
? String(count: pad, repeatedValue: with) + self | |
: self | |
} | |
} | |
func timeRun<T>(name: String, f: ()->T) -> String { | |
let start = CFAbsoluteTimeGetCurrent() | |
let result = f() | |
let end = CFAbsoluteTimeGetCurrent() | |
let timeStr = toString(Int((end - start) * 1_000_000)).lpad(to: 12, with: " ") | |
return "\(name)\t\(timeStr)µs, produced \(result)" | |
} | |
let n = 10_000_000 | |
let seed = Int(arc4random_uniform(10)) | |
let runs = [ | |
("Generic rand", { generateUsingGeneric(RandomGenerator(), n) }), | |
("Protocol rand", { generateUsingProtocol(RandomGenerator(), n) }), | |
("Generic const", { generateUsingGeneric(ConstantGenerator(constant: seed), n) }), | |
("Protocol const", { generateUsingProtocol(ConstantGenerator(constant: seed), n) }), | |
("Generic incr", { generateUsingGeneric(IncrementingGenerator(start: seed), n) }), | |
("Protocol incr", { generateUsingProtocol(IncrementingGenerator(start: seed), n) }), | |
] | |
println("\n".join(map(runs, timeRun))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment