-
Notifications
You must be signed in to change notification settings - Fork 431
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Lock-free disposal. #107
Lock-free disposal. #107
Conversation
18a79c2
to
71b2d27
Compare
DisposablePerfTests.swift
macOS: 2.4 GHz Intel Core i5-4258U, macOS 10.12.1, Xcode 8.1 * |
9e35154
to
cc435b2
Compare
I've factored out the lock-free logic, and wrapped it with a finite state machine-ish interface. It is a little bit faster too, with the inlining annotation in place. With the same test and configuration, it completes in 0.010 sec (10%). * Transitions are represented as protocol extensions. Tried tuples and type parameter, but both have a nontrivial cost at runtime. |
5ee7e49
to
9fbf8c2
Compare
Comparison across branches. The test case is sort of simulating a fast scrolling table view, which gets a bunch of composed properties (2 signals per transform) rebinding agains the cells.
func testProducerStart() {
let property = MutableProperty(1).map { $0 + 1 }.map { $0 + 1 }.map { $0 + 1 }
let token = Lifetime.Token()
let lifetime = Lifetime(token)
var i = 0
let target = BindingTarget(lifetime: lifetime, setter: { i = $0 })
measure {
for i in 0 ..< 10000 {
let d = target <~ property
d.dispose()
}
}
} |
c55b19e
to
c3f4fc9
Compare
`Bag` is unordered by contract, so there is no point to reverse it.
c3f4fc9
to
59dc77c
Compare
Awesome work!! |
Disposable
is crucial part of the signal resource management, especially in transformed signals andSignalProducer
s.Previous attempt: ReactiveCocoa/ReactiveCocoa#2463
This PR focuses on justDisposable
. All disposables have aDisposableState
, which exposes accessors built on top of OSAtomic primitives.DisposableState
is made astruct
so that the state is embedded into the containing class without extra indirection.This PR introduces a lock-free primitive
UnsafeAtomicState
, and refactored all disposable types to use it. Note that the primitive is marked withUnsafe
as it requires manual memory management.Note that while
CompositeDisposable
andSerialDisposable
still useAtomic
for storing their children, they may still benefit from the fast atomic boolean checks.The result is pretty impressive. For 1000000 iterations of
disposable.dispose()
(just a CAS) with whole module optimization, lock-freeSimpleDisposable
completed in just 0.011 seconds (12% SD), whileAtomic<Bool>
took 0.233 sec (4% SD).Less joules. 😸
--
This includes also a 1.5-2x fasterBag.forEach
overload under-Owholemodule
and-Ounchecked
.