Created
November 14, 2019 12:15
-
-
Save toshi0383/21d01dc9e9f23f979b360d1d75329fb2 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
// comparing atomic operation performance | |
import Concurrency | |
import Foundation | |
final class Locking { | |
static let shared = Locking() | |
private(set) var isLocked: Bool = false | |
private let _lock = NSLock() | |
func lock() { | |
_lock.lock(); defer { _lock.unlock(); } | |
if isLocked { return } | |
isLocked = true | |
} | |
func unlock() { | |
_lock.lock(); defer { _lock.unlock(); } | |
isLocked = false | |
} | |
} | |
final class Atomic<A> { | |
private let queue = DispatchQueue(label: "Atomic serial queue") | |
private var _value: A | |
init(_ value: A) { | |
self._value = value | |
} | |
var value: A { | |
get { | |
return queue.sync { self._value } | |
} | |
} | |
func mutate(_ transform: (inout A) -> ()) { | |
queue.sync { | |
transform(&self._value) | |
} | |
} | |
} | |
extension Date { | |
var millisecondsSince1970:Int64 { | |
return Int64((self.timeIntervalSince1970 * 1000.0).rounded()) | |
} | |
init(milliseconds:Int64) { | |
self = Date(timeIntervalSince1970: TimeInterval(milliseconds) / 1000) | |
} | |
} | |
func measure(_ f: () -> ()) { | |
let begin = Date().millisecondsSince1970 | |
f() | |
let end = Date().millisecondsSince1970 | |
print(end - begin) | |
} | |
let l = Locking.shared | |
let a = Atomic(false) | |
let uber = AtomicBool(initialValue: false) | |
let range = (0..<1000000) | |
measure { | |
range.forEach { _ in l.lock(); l.unlock() } | |
} | |
measure { | |
range.forEach { _ in a.mutate { $0 = true }; a.mutate { $0 = false } } | |
} | |
measure { | |
range.forEach { _ in | |
uber.compareAndSet(expect: false, newValue: true) | |
uber.compareAndSet(expect: true, newValue: false) | |
} | |
} | |
measure { | |
range.forEach { _ in | |
_ = uber.getAndSet(newValue: true) | |
_ = uber.getAndSet(newValue: false) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment