Compare commits
3 Commits
103a09a4d3
...
ac87961e97
| Author | SHA1 | Date |
|---|---|---|
|
|
ac87961e97 | |
|
|
3c0f419970 | |
|
|
310734d2f8 |
|
|
@ -13,10 +13,16 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@_exported import CoreMetrics
|
||||
import Foundation
|
||||
import Dispatch
|
||||
|
||||
@_exported import class CoreMetrics.Timer
|
||||
|
||||
#if canImport(FoundationEssentials)
|
||||
import FoundationEssentials
|
||||
#else
|
||||
import Foundation
|
||||
#endif
|
||||
|
||||
extension Timer {
|
||||
/// Convenience for measuring duration of a closure.
|
||||
///
|
||||
|
|
@ -112,4 +118,44 @@ extension Timer {
|
|||
|
||||
self.recordNanoseconds(nanoseconds.partialValue)
|
||||
}
|
||||
|
||||
#if compiler(>=6.0)
|
||||
/// Convenience for measuring duration of a closure.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - clock: The clock used for measuring the duration. Defaults to the continuous clock.
|
||||
/// - body: The closure to record the duration of.
|
||||
@inlinable
|
||||
@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)
|
||||
public func measure<Result, Failure: Error, Clock: _Concurrency.Clock>(
|
||||
clock: Clock = .continuous,
|
||||
body: () throws(Failure) -> Result
|
||||
) throws(Failure) -> Result where Clock.Duration == Duration {
|
||||
let start = clock.now
|
||||
defer {
|
||||
self.record(duration: start.duration(to: clock.now))
|
||||
}
|
||||
return try body()
|
||||
}
|
||||
|
||||
/// Convenience for measuring duration of a closure.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - clock: The clock used for measuring the duration. Defaults to the continuous clock.
|
||||
/// - isolation: The isolation of the method. Defaults to the isolation of the caller.
|
||||
/// - body: The closure to record the duration of.
|
||||
@inlinable
|
||||
@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)
|
||||
public func measure<Result, Failure: Error, Clock: _Concurrency.Clock>(
|
||||
clock: Clock = .continuous,
|
||||
isolation: isolated (any Actor)? = #isolation,
|
||||
body: () async throws(Failure) -> sending Result
|
||||
) async throws(Failure) -> sending Result where Clock.Duration == Duration {
|
||||
let start = clock.now
|
||||
defer {
|
||||
self.record(duration: start.duration(to: clock.now))
|
||||
}
|
||||
return try await body()
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -220,6 +220,43 @@ class MetricsExtensionsTests: XCTestCase {
|
|||
"expected value to match"
|
||||
)
|
||||
}
|
||||
|
||||
#if compiler(>=6.0)
|
||||
func testTimerMeasure() async throws {
|
||||
// bootstrap with our test metrics
|
||||
let metrics = TestMetrics()
|
||||
MetricsSystem.bootstrapInternal(metrics)
|
||||
// run the test
|
||||
let name = "timer-\(UUID().uuidString)"
|
||||
let delay = Duration.milliseconds(5)
|
||||
let timer = Timer(label: name)
|
||||
try await timer.measure {
|
||||
try await Task.sleep(for: delay)
|
||||
}
|
||||
|
||||
let expectedTimer = try metrics.expectTimer(name)
|
||||
XCTAssertEqual(1, expectedTimer.values.count, "expected number of entries to match")
|
||||
XCTAssertGreaterThan(expectedTimer.values[0], delay.nanosecondsClamped, "expected delay to match")
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func testTimerMeasureFromMainActor() async throws {
|
||||
// bootstrap with our test metrics
|
||||
let metrics = TestMetrics()
|
||||
MetricsSystem.bootstrapInternal(metrics)
|
||||
// run the test
|
||||
let name = "timer-\(UUID().uuidString)"
|
||||
let delay = Duration.milliseconds(5)
|
||||
let timer = Timer(label: name)
|
||||
try await timer.measure {
|
||||
try await Task.sleep(for: delay)
|
||||
}
|
||||
|
||||
let expectedTimer = try metrics.expectTimer(name)
|
||||
XCTAssertEqual(1, expectedTimer.values.count, "expected number of entries to match")
|
||||
XCTAssertGreaterThan(expectedTimer.values[0], delay.nanosecondsClamped, "expected delay to match")
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// https://bugs.swift.org/browse/SR-6310
|
||||
|
|
@ -251,3 +288,25 @@ extension DispatchTimeInterval {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if swift(>=5.7)
|
||||
@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)
|
||||
extension Swift.Duration {
|
||||
fileprivate var nanosecondsClamped: Int64 {
|
||||
let components = self.components
|
||||
|
||||
let secondsComponentNanos = components.seconds.multipliedReportingOverflow(by: 1_000_000_000)
|
||||
let attosCompononentNanos = components.attoseconds / 1_000_000_000
|
||||
let combinedNanos = secondsComponentNanos.partialValue.addingReportingOverflow(attosCompononentNanos)
|
||||
|
||||
guard
|
||||
!secondsComponentNanos.overflow,
|
||||
!combinedNanos.overflow
|
||||
else {
|
||||
return .max
|
||||
}
|
||||
|
||||
return combinedNanos.partialValue
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue