Make our time types transparent (#2374)
Motivation: Our time types are trivial, and they should be fully transparent. This produces minor performance improvements in code handling time types, but is mostly useful in terms of allowing the compiler to observe that these functions have no side effects, thereby eliding some ARC traffic. Modifications: Make our time types inlinable. Result: Better performance.
This commit is contained in:
parent
4dfae01cc6
commit
108d4646a9
|
@ -445,7 +445,8 @@ public struct TimeAmount: Hashable, Sendable {
|
||||||
/// The nanoseconds representation of the `TimeAmount`.
|
/// The nanoseconds representation of the `TimeAmount`.
|
||||||
public let nanoseconds: Int64
|
public let nanoseconds: Int64
|
||||||
|
|
||||||
private init(_ nanoseconds: Int64) {
|
/* private but */ @inlinable
|
||||||
|
init(_ nanoseconds: Int64) {
|
||||||
self.nanoseconds = nanoseconds
|
self.nanoseconds = nanoseconds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,6 +455,7 @@ public struct TimeAmount: Hashable, Sendable {
|
||||||
/// - parameters:
|
/// - parameters:
|
||||||
/// - amount: the amount of nanoseconds this `TimeAmount` represents.
|
/// - amount: the amount of nanoseconds this `TimeAmount` represents.
|
||||||
/// - returns: the `TimeAmount` for the given amount.
|
/// - returns: the `TimeAmount` for the given amount.
|
||||||
|
@inlinable
|
||||||
public static func nanoseconds(_ amount: Int64) -> TimeAmount {
|
public static func nanoseconds(_ amount: Int64) -> TimeAmount {
|
||||||
return TimeAmount(amount)
|
return TimeAmount(amount)
|
||||||
}
|
}
|
||||||
|
@ -463,6 +465,7 @@ public struct TimeAmount: Hashable, Sendable {
|
||||||
/// - parameters:
|
/// - parameters:
|
||||||
/// - amount: the amount of microseconds this `TimeAmount` represents.
|
/// - amount: the amount of microseconds this `TimeAmount` represents.
|
||||||
/// - returns: the `TimeAmount` for the given amount.
|
/// - returns: the `TimeAmount` for the given amount.
|
||||||
|
@inlinable
|
||||||
public static func microseconds(_ amount: Int64) -> TimeAmount {
|
public static func microseconds(_ amount: Int64) -> TimeAmount {
|
||||||
return TimeAmount(amount * 1000)
|
return TimeAmount(amount * 1000)
|
||||||
}
|
}
|
||||||
|
@ -472,6 +475,7 @@ public struct TimeAmount: Hashable, Sendable {
|
||||||
/// - parameters:
|
/// - parameters:
|
||||||
/// - amount: the amount of milliseconds this `TimeAmount` represents.
|
/// - amount: the amount of milliseconds this `TimeAmount` represents.
|
||||||
/// - returns: the `TimeAmount` for the given amount.
|
/// - returns: the `TimeAmount` for the given amount.
|
||||||
|
@inlinable
|
||||||
public static func milliseconds(_ amount: Int64) -> TimeAmount {
|
public static func milliseconds(_ amount: Int64) -> TimeAmount {
|
||||||
return TimeAmount(amount * (1000 * 1000))
|
return TimeAmount(amount * (1000 * 1000))
|
||||||
}
|
}
|
||||||
|
@ -481,6 +485,7 @@ public struct TimeAmount: Hashable, Sendable {
|
||||||
/// - parameters:
|
/// - parameters:
|
||||||
/// - amount: the amount of seconds this `TimeAmount` represents.
|
/// - amount: the amount of seconds this `TimeAmount` represents.
|
||||||
/// - returns: the `TimeAmount` for the given amount.
|
/// - returns: the `TimeAmount` for the given amount.
|
||||||
|
@inlinable
|
||||||
public static func seconds(_ amount: Int64) -> TimeAmount {
|
public static func seconds(_ amount: Int64) -> TimeAmount {
|
||||||
return TimeAmount(amount * (1000 * 1000 * 1000))
|
return TimeAmount(amount * (1000 * 1000 * 1000))
|
||||||
}
|
}
|
||||||
|
@ -490,6 +495,7 @@ public struct TimeAmount: Hashable, Sendable {
|
||||||
/// - parameters:
|
/// - parameters:
|
||||||
/// - amount: the amount of minutes this `TimeAmount` represents.
|
/// - amount: the amount of minutes this `TimeAmount` represents.
|
||||||
/// - returns: the `TimeAmount` for the given amount.
|
/// - returns: the `TimeAmount` for the given amount.
|
||||||
|
@inlinable
|
||||||
public static func minutes(_ amount: Int64) -> TimeAmount {
|
public static func minutes(_ amount: Int64) -> TimeAmount {
|
||||||
return TimeAmount(amount * (1000 * 1000 * 1000 * 60))
|
return TimeAmount(amount * (1000 * 1000 * 1000 * 60))
|
||||||
}
|
}
|
||||||
|
@ -499,12 +505,14 @@ public struct TimeAmount: Hashable, Sendable {
|
||||||
/// - parameters:
|
/// - parameters:
|
||||||
/// - amount: the amount of hours this `TimeAmount` represents.
|
/// - amount: the amount of hours this `TimeAmount` represents.
|
||||||
/// - returns: the `TimeAmount` for the given amount.
|
/// - returns: the `TimeAmount` for the given amount.
|
||||||
|
@inlinable
|
||||||
public static func hours(_ amount: Int64) -> TimeAmount {
|
public static func hours(_ amount: Int64) -> TimeAmount {
|
||||||
return TimeAmount(amount * (1000 * 1000 * 1000 * 60 * 60))
|
return TimeAmount(amount * (1000 * 1000 * 1000 * 60 * 60))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TimeAmount: Comparable {
|
extension TimeAmount: Comparable {
|
||||||
|
@inlinable
|
||||||
public static func < (lhs: TimeAmount, rhs: TimeAmount) -> Bool {
|
public static func < (lhs: TimeAmount, rhs: TimeAmount) -> Bool {
|
||||||
return lhs.nanoseconds < rhs.nanoseconds
|
return lhs.nanoseconds < rhs.nanoseconds
|
||||||
}
|
}
|
||||||
|
@ -512,30 +520,37 @@ extension TimeAmount: Comparable {
|
||||||
|
|
||||||
extension TimeAmount: AdditiveArithmetic {
|
extension TimeAmount: AdditiveArithmetic {
|
||||||
/// The zero value for `TimeAmount`.
|
/// The zero value for `TimeAmount`.
|
||||||
|
@inlinable
|
||||||
public static var zero: TimeAmount {
|
public static var zero: TimeAmount {
|
||||||
return TimeAmount.nanoseconds(0)
|
return TimeAmount.nanoseconds(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@inlinable
|
||||||
public static func + (lhs: TimeAmount, rhs: TimeAmount) -> TimeAmount {
|
public static func + (lhs: TimeAmount, rhs: TimeAmount) -> TimeAmount {
|
||||||
return TimeAmount(lhs.nanoseconds + rhs.nanoseconds)
|
return TimeAmount(lhs.nanoseconds + rhs.nanoseconds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@inlinable
|
||||||
public static func +=(lhs: inout TimeAmount, rhs: TimeAmount) {
|
public static func +=(lhs: inout TimeAmount, rhs: TimeAmount) {
|
||||||
lhs = lhs + rhs
|
lhs = lhs + rhs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@inlinable
|
||||||
public static func - (lhs: TimeAmount, rhs: TimeAmount) -> TimeAmount {
|
public static func - (lhs: TimeAmount, rhs: TimeAmount) -> TimeAmount {
|
||||||
return TimeAmount(lhs.nanoseconds - rhs.nanoseconds)
|
return TimeAmount(lhs.nanoseconds - rhs.nanoseconds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@inlinable
|
||||||
public static func -=(lhs: inout TimeAmount, rhs: TimeAmount) {
|
public static func -=(lhs: inout TimeAmount, rhs: TimeAmount) {
|
||||||
lhs = lhs - rhs
|
lhs = lhs - rhs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@inlinable
|
||||||
public static func * <T: BinaryInteger>(lhs: T, rhs: TimeAmount) -> TimeAmount {
|
public static func * <T: BinaryInteger>(lhs: T, rhs: TimeAmount) -> TimeAmount {
|
||||||
return TimeAmount(Int64(lhs) * rhs.nanoseconds)
|
return TimeAmount(Int64(lhs) * rhs.nanoseconds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@inlinable
|
||||||
public static func * <T: BinaryInteger>(lhs: TimeAmount, rhs: T) -> TimeAmount {
|
public static func * <T: BinaryInteger>(lhs: TimeAmount, rhs: T) -> TimeAmount {
|
||||||
return TimeAmount(lhs.nanoseconds * Int64(rhs))
|
return TimeAmount(lhs.nanoseconds * Int64(rhs))
|
||||||
}
|
}
|
||||||
|
@ -563,13 +578,14 @@ public struct NIODeadline: Equatable, Hashable, Sendable {
|
||||||
public typealias Value = UInt64
|
public typealias Value = UInt64
|
||||||
|
|
||||||
// This really should be an UInt63 but we model it as Int64 with >=0 assert
|
// This really should be an UInt63 but we model it as Int64 with >=0 assert
|
||||||
private var _uptimeNanoseconds: Int64 {
|
/* private but */ @usableFromInline var _uptimeNanoseconds: Int64 {
|
||||||
didSet {
|
didSet {
|
||||||
assert(self._uptimeNanoseconds >= 0)
|
assert(self._uptimeNanoseconds >= 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The nanoseconds since boot representation of the `NIODeadline`.
|
/// The nanoseconds since boot representation of the `NIODeadline`.
|
||||||
|
@inlinable
|
||||||
public var uptimeNanoseconds: UInt64 {
|
public var uptimeNanoseconds: UInt64 {
|
||||||
return .init(self._uptimeNanoseconds)
|
return .init(self._uptimeNanoseconds)
|
||||||
}
|
}
|
||||||
|
@ -577,7 +593,7 @@ public struct NIODeadline: Equatable, Hashable, Sendable {
|
||||||
public static let distantPast = NIODeadline(0)
|
public static let distantPast = NIODeadline(0)
|
||||||
public static let distantFuture = NIODeadline(.init(Int64.max))
|
public static let distantFuture = NIODeadline(.init(Int64.max))
|
||||||
|
|
||||||
private init(_ nanoseconds: Int64) {
|
/* private but */ @inlinable init(_ nanoseconds: Int64) {
|
||||||
precondition(nanoseconds >= 0)
|
precondition(nanoseconds >= 0)
|
||||||
self._uptimeNanoseconds = nanoseconds
|
self._uptimeNanoseconds = nanoseconds
|
||||||
}
|
}
|
||||||
|
@ -593,8 +609,8 @@ public struct NIODeadline: Equatable, Hashable, Sendable {
|
||||||
/// we make that call here, directly from NIO.
|
/// we make that call here, directly from NIO.
|
||||||
///
|
///
|
||||||
/// - TODO: Investigate optimizing the call to `DispatchTime.now()` away on other platforms too.
|
/// - TODO: Investigate optimizing the call to `DispatchTime.now()` away on other platforms too.
|
||||||
@inline(__always)
|
@inlinable
|
||||||
private static func timeNow() -> UInt64 {
|
static func timeNow() -> UInt64 {
|
||||||
#if os(Linux)
|
#if os(Linux)
|
||||||
var ts = timespec()
|
var ts = timespec()
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts)
|
clock_gettime(CLOCK_MONOTONIC, &ts)
|
||||||
|
@ -607,38 +623,55 @@ public struct NIODeadline: Equatable, Hashable, Sendable {
|
||||||
#endif // os(Linux)
|
#endif // os(Linux)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@inlinable
|
||||||
public static func now() -> NIODeadline {
|
public static func now() -> NIODeadline {
|
||||||
return NIODeadline.uptimeNanoseconds(timeNow())
|
return NIODeadline.uptimeNanoseconds(timeNow())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@inlinable
|
||||||
public static func uptimeNanoseconds(_ nanoseconds: UInt64) -> NIODeadline {
|
public static func uptimeNanoseconds(_ nanoseconds: UInt64) -> NIODeadline {
|
||||||
return NIODeadline(Int64(min(UInt64(Int64.max), nanoseconds)))
|
return NIODeadline(Int64(min(UInt64(Int64.max), nanoseconds)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@inlinable
|
||||||
|
public static func == (lhs: NIODeadline, rhs: NIODeadline) -> Bool {
|
||||||
|
return lhs.uptimeNanoseconds == rhs.uptimeNanoseconds
|
||||||
|
}
|
||||||
|
|
||||||
|
@inlinable
|
||||||
|
public func hash(into hasher: inout Hasher) {
|
||||||
|
hasher.combine(self.uptimeNanoseconds)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension NIODeadline: Comparable {
|
extension NIODeadline: Comparable {
|
||||||
|
@inlinable
|
||||||
public static func < (lhs: NIODeadline, rhs: NIODeadline) -> Bool {
|
public static func < (lhs: NIODeadline, rhs: NIODeadline) -> Bool {
|
||||||
return lhs.uptimeNanoseconds < rhs.uptimeNanoseconds
|
return lhs.uptimeNanoseconds < rhs.uptimeNanoseconds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@inlinable
|
||||||
public static func > (lhs: NIODeadline, rhs: NIODeadline) -> Bool {
|
public static func > (lhs: NIODeadline, rhs: NIODeadline) -> Bool {
|
||||||
return lhs.uptimeNanoseconds > rhs.uptimeNanoseconds
|
return lhs.uptimeNanoseconds > rhs.uptimeNanoseconds
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension NIODeadline: CustomStringConvertible {
|
extension NIODeadline: CustomStringConvertible {
|
||||||
|
@inlinable
|
||||||
public var description: String {
|
public var description: String {
|
||||||
return self.uptimeNanoseconds.description
|
return self.uptimeNanoseconds.description
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension NIODeadline {
|
extension NIODeadline {
|
||||||
|
@inlinable
|
||||||
public static func - (lhs: NIODeadline, rhs: NIODeadline) -> TimeAmount {
|
public static func - (lhs: NIODeadline, rhs: NIODeadline) -> TimeAmount {
|
||||||
// This won't ever crash, NIODeadlines are guaranteed to be within 0 ..< 2^63-1 nanoseconds so the result can
|
// This won't ever crash, NIODeadlines are guaranteed to be within 0 ..< 2^63-1 nanoseconds so the result can
|
||||||
// definitely be stored in a TimeAmount (which is an Int64).
|
// definitely be stored in a TimeAmount (which is an Int64).
|
||||||
return .nanoseconds(Int64(lhs.uptimeNanoseconds) - Int64(rhs.uptimeNanoseconds))
|
return .nanoseconds(Int64(lhs.uptimeNanoseconds) - Int64(rhs.uptimeNanoseconds))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@inlinable
|
||||||
public static func + (lhs: NIODeadline, rhs: TimeAmount) -> NIODeadline {
|
public static func + (lhs: NIODeadline, rhs: TimeAmount) -> NIODeadline {
|
||||||
let partial: Int64
|
let partial: Int64
|
||||||
let overflow: Bool
|
let overflow: Bool
|
||||||
|
@ -653,6 +686,7 @@ extension NIODeadline {
|
||||||
return NIODeadline(partial)
|
return NIODeadline(partial)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@inlinable
|
||||||
public static func - (lhs: NIODeadline, rhs: TimeAmount) -> NIODeadline {
|
public static func - (lhs: NIODeadline, rhs: TimeAmount) -> NIODeadline {
|
||||||
if rhs.nanoseconds < 0 {
|
if rhs.nanoseconds < 0 {
|
||||||
// The addition won't crash because the worst that could happen is `UInt64(Int64.max) + UInt64(Int64.max)`
|
// The addition won't crash because the worst that could happen is `UInt64(Int64.max) + UInt64(Int64.max)`
|
||||||
|
|
Loading…
Reference in New Issue