Skip to content

Instantly share code, notes, and snippets.

@ZevEisenberg
Last active March 16, 2022 01:54
Show Gist options
  • Save ZevEisenberg/b86c391f573551a55a4718de5a0b6bbc to your computer and use it in GitHub Desktop.
Save ZevEisenberg/b86c391f573551a55a4718de5a0b6bbc to your computer and use it in GitHub Desktop.
Use os_signpost for performance logging of transformations in RxSwift
// RxSwift signposts
import os.signpost
import RxSwift
func signpost<T>(log: OSLog, name: StaticString, value: String, _ thing: () throws -> T) rethrows -> T {
let signpostID = OSSignpostID(log: log)
os_signpost(
.begin,
log: log,
name: name,
signpostID: signpostID,
"%{public}s",
value
)
let result = try thing()
os_signpost(
.end,
log: log,
name: name,
signpostID: signpostID,
"%{public}s",
value
)
return result
}
extension ObservableType {
/// Projects each element of an observable sequence into a new form.
/// Also uses os_signpost to log the duration of transformation.
/// Useful for performance debugging.
///
/// - Parameters:
/// - log: an instance of OSLog to use for logging
/// - name: The name of the event, e.g. "decode image"
/// - logMessageGenerator: A closure that takes the value to be
/// transformed as input and returns some meaningful information
/// as output. Useful to identify which operation is occurring.
/// For example, { $0.imageURL }.
/// - transform: A transform function to apply to each source element.
/// - Returns: An observable sequence whose elements are the result
/// of invoking the transform function on each element of source.
func mapAndSignpost<T>(log: OSLog, name: StaticString, logMessageGenerator: @escaping (Element) -> String, _ transform: @escaping (Self.Element) throws -> T) -> Observable<T> {
return self.map {
let signpostID = OSSignpostID(log: log)
let message = logMessageGenerator($0)
os_signpost(
.begin,
log: log,
name: name,
signpostID: signpostID,
"%{public}s",
message
)
let result = try transform($0)
os_signpost(
.end,
log: log,
name: name,
signpostID: signpostID,
"%{public}s",
message
)
return result
}
}
func startSignpost(on log: OSLog, message: String) -> Observable<Element> {
let dict = Thread.current.threadDictionary
let id = OSSignpostID(log: log)
dict["myCoolSignpostID"] = id
dict["myCoolLogger"] = log
return self.do(onNext: { _ in
os_signpost(
.begin,
log: log,
name: "Name",
signpostID: id,
"%{public}s",
message
)
})
}
func endSignpost() -> Observable<Element> {
let dict = Thread.current.threadDictionary
let id = dict["myCoolSignpostID"] as! OSSignpostID
let log = dict["myCoolLogger"] as! OSLog
return self.do(onNext: { _ in
os_signpost(
.end,
log: log,
name: "Name",
signpostID: id,
"%{public}s",
"message"
)
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment