Skip to content

Instantly share code, notes, and snippets.

@dydus0x14
Created November 10, 2020 13:58
Show Gist options
  • Save dydus0x14/516f84695ad39496123731d9a9a4fe4a to your computer and use it in GitHub Desktop.
Save dydus0x14/516f84695ad39496123731d9a9a4fe4a to your computer and use it in GitHub Desktop.
protocol Atomic {
var value: Int { get }
func increment()
}
class SwiftAtomic: Atomic {
private let counter = ManagedAtomic<Int>(0)
var value: Int {
counter.load(ordering: .relaxed)
}
func increment() {
counter.wrappingIncrement(ordering: .relaxed)
}
}
class QueueAtomic: Atomic {
private var counter = 0
private let queue = DispatchQueue(label: "")
var value: Int {
queue.sync {
self.counter
}
}
func increment() {
queue.sync {
self.counter += 1
}
}
}
class NSLockAtomic: Atomic {
private var counter = 0
private let lock = NSLock()
var value: Int {
var result = 0
lock.lock()
result = counter
lock.unlock()
return result
}
func increment() {
lock.lock()
counter += 1
lock.unlock()
}
}
class SpinLock: Atomic {
var lock = os_unfair_lock()
var counter = 0
var value: Int {
var result = 0
os_unfair_lock_lock(&lock)
result = counter
os_unfair_lock_unlock(&lock)
return result
}
func increment() {
os_unfair_lock_lock(&lock)
counter += 1
os_unfair_lock_unlock(&lock)
}
}
class AtomicTest {
func run() {
for index in 1...10 {
let swiftAtomic = SwiftAtomic()
let queueAtomic = QueueAtomic()
let nslockAtomic = NSLockAtomic()
let spinlockAtomic = SpinLock()
let time1 = measure {
self.run(iterations: index, counter: swiftAtomic)
}
let time2 = measure {
self.run(iterations: index, counter: queueAtomic)
}
let time3 = measure {
self.run(iterations: index, counter: nslockAtomic)
}
let time4 = measure {
self.run(iterations: index, counter: spinlockAtomic)
}
print(String(format: "%.3f;%.3f;%.3f;%.3f", time1, time2, time3, time4))
}
}
func run(iterations: Int, counter: Atomic) {
DispatchQueue.concurrentPerform(iterations: iterations) { _ in
for index in 0 ..< 1_000_000 {
if index % 100 == 0 {
_ = counter.value
} else {
counter.increment()
}
}
}
}
func measure(block: () -> Void) -> TimeInterval {
let startTime = CFAbsoluteTimeGetCurrent()
block()
let endTime = CFAbsoluteTimeGetCurrent()
let totalTime = endTime - startTime
return totalTime
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment