Skip to content

Instantly share code, notes, and snippets.

@andersio
Created December 2, 2016 23:17
Show Gist options
  • Select an option

  • Save andersio/70ded6fb313df4ebeed19e98b50ea77a to your computer and use it in GitHub Desktop.

Select an option

Save andersio/70ded6fb313df4ebeed19e98b50ea77a to your computer and use it in GitHub Desktop.
import ReactiveSwift
import Result
import XCTest
class CwlSignalTests: XCTestCase {
// Credits:
// CwlSignal
//
// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// https://github.com/mattgallagher/CwlSignal/blob/master/CwlSignalTests/CwlSignalTests.swift
func testSinglePerformance() {
//#if DEBUG
// let sequenceLength = 10_000
// let expected = 0.015 // +/- 0.15
// let upperThreshold = 0.5
//#else
let sequenceLength = 10_000_000
let expected = 3.0 // +/- 0.4
let upperThreshold = 4.0
//#endif
let t = mach_absolute_time()
var count = 0
// A basic test designed to exercise (sequence -> SignalInput -> SignalNode -> SignalQueue) performance.
let (signal, observer) = Signal<Int, NoError>.pipe()
signal.observe { r in
switch r {
case .value: count += 1
default: break
}
}
for v in 0..<sequenceLength {
observer.send(value: v)
}
observer.sendCompleted()
XCTAssert(count == sequenceLength)
let elapsed = 1e-9 * Double(mach_absolute_time() - t)
XCTAssert(elapsed < upperThreshold)
print("Performance is \(elapsed) seconds versus expected \(expected). Rate is \(Double(sequenceLength) / elapsed) per second.")
// Approximate analogue to Signal architecture (sequence -> lazy map to Result -> iterate -> unwrap)
let t2 = mach_absolute_time()
var count2 = 0
(0..<sequenceLength).lazy.map(noInlineEventValueMap).forEach { r in
switch r {
case .value: count2 += 1
default: break
}
}
XCTAssert(count2 == sequenceLength)
let elapsed2 = 1e-9 * Double(mach_absolute_time() - t2)
print("Baseline is is \(elapsed2) seconds (\(elapsed / elapsed2) times faster).")
}
@inline(never)
private func noInlineEventValueMap<V>(_ v: V) -> Event<V, NoError> {
return Event.value(v)
}
@available(macOS 10.10, *)
func testAsyncMapPerformance() {
//#if DEBUG
// let sequenceLength = 10_000
// let expected = 0.02 // +/- 0.15
//#else
let sequenceLength = 1_000_000
let expected = 3.3 // +/- 0.4
//#endif
let t1 = mach_absolute_time()
var count1 = 0
let ex = expectation(description: "Waiting for signal")
// A basic test designed to exercise (sequence -> SignalInput -> SignalNode -> SignalQueue) performance.
let ep = SignalProducer<Int, NoError> { input, _ in
for v in 0..<sequenceLength {
input.send(value: v)
}
input.sendCompleted()
}
.observe(on: QueueScheduler())
.map { $0 }
.observe(on: UIScheduler())
.startWithValues { v in
count1 += 1
if count1 == sequenceLength {
ex.fulfill()
}
}
waitForExpectations(timeout: 1e2, handler: nil)
withExtendedLifetime(ep) {}
precondition(count1 == sequenceLength)
let elapsed1 = 1e-9 * Double(mach_absolute_time() - t1)
print("Performance is \(elapsed1) seconds versus expected \(expected). Rate is \(Double(sequenceLength) / elapsed1) per second.")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment