Created
October 7, 2017 02:50
-
-
Save acrookston/7a0d29c14d264919d1cd6167d570f991 to your computer and use it in GitHub Desktop.
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
// Results: | |
// 0.40788197517395 - IteratedEnum (it's slow due to EnumCollection) | |
// 0.282593011856079 - StaticIteratedEnum | |
// 0.152174055576324 - SwitchedEnum | |
// 0.159240961074829 - OtherSwitchedEnum | |
import Foundation | |
// MARK: - Benchmark - gotta know how fast it is! | |
func benchmark(_ operation: ()->()) -> Double { | |
let startTime = CFAbsoluteTimeGetCurrent() | |
operation() | |
let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime | |
return Double(timeElapsed) | |
} | |
// MARK: - Enum extension - lifesaver :) | |
protocol EnumCollection : Hashable {} | |
extension EnumCollection { | |
static func enumerated() -> AnySequence<Self> { | |
typealias S = Self | |
return AnySequence { () -> AnyIterator<S> in | |
var raw = 0 | |
return AnyIterator { | |
let current = withUnsafePointer(to: &raw) { | |
$0.withMemoryRebound(to: S.self, capacity: 1) { $0.pointee } | |
} | |
guard current.hashValue == raw else { return nil } | |
raw += 1 | |
return current | |
} | |
} | |
} | |
} | |
enum IteratedEnum: EnumCollection { | |
case one, two | |
@discardableResult init?(searching: String) { | |
for item in IteratedEnum.enumerated() { | |
if searching.contains(item.matcher) { | |
self = item | |
return | |
} | |
} | |
return nil | |
} | |
// If you don't want to make it a String enum `case one = "one" | |
private var matcher: String { | |
switch self { | |
case .one: | |
return "one" | |
case .two: | |
return "two" | |
} | |
} | |
} | |
enum StaticIteratedEnum: String { | |
case one = "one" | |
case two = "two" | |
static let all: [StaticIteratedEnum] = [.one, .two] | |
@discardableResult init?(searching: String) { | |
for item in StaticIteratedEnum.all { | |
if searching.contains(item.rawValue) { | |
self = item | |
return | |
} | |
} | |
return nil | |
} | |
} | |
enum SwitchedEnum: EnumCollection { | |
case one, two | |
@discardableResult init?(searching: String) { | |
switch true { | |
case searching.contains("one"): | |
self = .one | |
case searching.contains("two"): | |
self = .two | |
default: | |
return nil | |
} | |
} | |
} | |
enum OtherSwitchedEnum: EnumCollection { | |
case one, two | |
@discardableResult init?(searching: String) { | |
switch searching { | |
case _ where searching.contains("one"): | |
self = .one | |
case _ where searching.contains("two"): | |
self = .two | |
default: | |
return nil | |
} | |
} | |
} | |
assert(IteratedEnum(searching: "one") == .one) | |
assert(IteratedEnum(searching: "two") == .two) | |
assert(StaticIteratedEnum(searching: "one") == .one) | |
assert(StaticIteratedEnum(searching: "two") == .two) | |
assert(SwitchedEnum(searching: "one") == .one) | |
assert(SwitchedEnum(searching: "two") == .two) | |
assert(OtherSwitchedEnum(searching: "one") == .one) | |
assert(OtherSwitchedEnum(searching: "two") == .two) | |
let cases = ["One time", "one", "two", "four", "two times"] | |
let count = UInt32(cases.count) | |
let sample = (0...100000).map { _ in cases[Int(arc4random_uniform(count))] } | |
print(benchmark { | |
for i in sample { | |
IteratedEnum(searching: i) | |
} | |
}) | |
print(benchmark { | |
for i in sample { | |
StaticIteratedEnum(searching: i) | |
} | |
}) | |
print(benchmark { | |
for i in sample { | |
SwitchedEnum(searching: i) | |
} | |
}) | |
print(benchmark { | |
for i in sample { | |
OtherSwitchedEnum(searching: i) | |
} | |
}) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment