Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save marciniwanicki/70e89b5dd93ff405e49d6ccd93b854e8 to your computer and use it in GitHub Desktop.
Save marciniwanicki/70e89b5dd93ff405e49d6ccd93b854e8 to your computer and use it in GitHub Desktop.
//
// Created by Marcin Iwanicki on 10/07/2018.
// Copyright © 2018 Marcin Iwanicki. All rights reserved.
//
import XCTest
// -----------------------------------------------------------------------------
// Tests
// -----------------------------------------------------------------------------
class SwiftSyncTestTests: XCTestCase {
private let iterations = 100000
func testCreateNSLock() {
printTestName("Create - NSLock")
measure {
for _ in 0...iterations {
_ = NSLock()
}
}
}
func testCreateDispatchQueue() {
printTestName("Create - DispatchQueue")
measure {
for _ in 0...iterations {
_ = DispatchQueue(label: "test")
}
}
}
func testCreateDispatchSemaphore() {
printTestName("Create - DispatchSemaphore")
measure {
for _ in 0...iterations {
_ = DispatchSemaphore(value: 1)
}
}
}
func testCreateTimeLockSynchronize() {
printTestName("Create - LockSynchronize")
measure {
for _ in 0...iterations {
_ = LockSynchronize()
}
}
}
func testCreateTimeDispatchQueueSynchronize() {
printTestName("Create - DispatchQueueSynchronize")
measure {
for _ in 0...iterations {
_ = DispatchQueueSynchronize()
}
}
}
func testCreateTimeDispatchSemaphoreSynchronize() {
printTestName("Create - DispatchSemaphoreSynchronize")
measure {
for _ in 0...iterations {
_ = DispatchSemaphoreSynchronize()
}
}
}
func testWriteSameThreadLockSynchronize() {
printTestName("Write same thread - LockSynchronize")
performWriteSameThread(LockSynchronize())
}
func testWriteSameThreadDispatchQueueSynchronize() {
printTestName("Write same thread - DispatchQueue")
performWriteSameThread(DispatchQueueSynchronize())
}
func testReadSameThreadLockSynchronize() {
printTestName("Read same thread - Lock")
performReadSameThread(LockSynchronize())
}
func testReadSameThreadDispatchQueueSynchronize() {
printTestName("Read same thread - DispatchQueue")
performReadSameThread(DispatchQueueSynchronize())
}
func testReadWriteRandomThreadsLockSynchronize() {
printTestName("Read write random thread - Lock")
performReadWriteRandomThread(LockSynchronize())
}
func testReadWriteRandomThreadDispatchQueueSynchronize() {
printTestName("Read write random thread - DispatchQueue")
performReadWriteRandomThread(DispatchQueueSynchronize())
}
private func performWriteSameThread(_ synchronize: Synchronize) {
let counter = Counter()
measure {
for _ in 0...iterations {
synchronize.write { counter.increment() }
}
}
}
private func performReadSameThread(_ synchronize: Synchronize) {
let counter = Counter()
measure {
for _ in 0...iterations {
_ = synchronize.read { counter.value }
}
}
}
private func performReadWriteRandomThread(_ synchronize: Synchronize) {
let iterations = 10000
let expectedValue = 2 * iterations
measure {
let expect = expectation(description: "Finish")
let counter = Counter()
for _ in 0..<iterations {
DispatchQueue.global(qos: .background).async {
synchronize.write {
counter.increment()
}
let value: Int = synchronize.read {
counter.increment()
return counter.value
}
if value == expectedValue { expect.fulfill() }
}
}
waitForExpectations(timeout: 60) { _ in }
}
}
private func printTestName(_ testName: String) {
print("\n")
print("****************************************************************")
print("\(testName)")
print("****************************************************************")
}
}
class Counter {
var value: Int = 0
func increment() {
value += 1
}
}
// -----------------------------------------------------------------------------
// Universal protocol
// -----------------------------------------------------------------------------
protocol Synchronize {
func write(_ closure: @escaping () -> Void)
func read<T>(_ closure: @escaping () -> T) -> T
}
// -----------------------------------------------------------------------------
// Tested implementations
// -----------------------------------------------------------------------------
class LockSynchronize: Synchronize {
private let lock = NSLock()
func write(_ closure: @escaping () -> Void) {
lock.lock(); defer { lock.unlock() }
closure()
}
func read<T>(_ closure: @escaping () -> T) -> T {
lock.lock(); defer { lock.unlock() }
return closure()
}
}
// -----------------------------------------------------------------------------
class DispatchQueueSynchronize: Synchronize {
private let queue = DispatchQueue(label: "dispatch_queue_synchronize")
func write(_ closure: @escaping () -> Void) {
queue.sync {
closure()
}
}
func read<T>(_ closure: @escaping () -> T) -> T {
return queue.sync {
return closure()
}
}
}
// -----------------------------------------------------------------------------
class DispatchSemaphoreSynchronize: Synchronize {
private let semaphore = DispatchSemaphore(value: 1)
func write(_ closure: @escaping () -> Void) {
semaphore.wait(); defer { semaphore.signal() }
closure()
}
func read<T>(_ closure: @escaping () -> T) -> T {
semaphore.wait(); defer { semaphore.signal() }
return closure()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment