-
Notifications
You must be signed in to change notification settings - Fork 3.6k
swift 6.0+ performance tweaks 3x-6x #9067
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,8 +26,9 @@ public struct ByteBuffer { | |
| /// deallocating the memory that was held by (memory: UnsafeMutableRawPointer) | ||
| @usableFromInline | ||
| final class Storage { | ||
| #if compiler(>=6.0) | ||
| @usableFromInline | ||
| enum Blob { | ||
| @frozen enum Blob: ~Copyable { | ||
| #if !os(WASI) | ||
| case data(Data) | ||
| case bytes(ContiguousBytes) | ||
|
|
@@ -36,15 +37,73 @@ public struct ByteBuffer { | |
| case byteBuffer(_InternalByteBuffer) | ||
| case array([UInt8]) | ||
| case pointer(UnsafeMutableRawPointer) | ||
|
|
||
| init(_ other: borrowing Blob) { | ||
| switch other { | ||
| case .data(let data): | ||
| self = .data(data) | ||
| case .bytes(let contiguousBytes): | ||
| self = .bytes(contiguousBytes) | ||
| case .byteBuffer(let internalByteBuffer): | ||
| self = .byteBuffer(internalByteBuffer) | ||
| case .array(let array): | ||
| self = .array(array) | ||
| case .pointer(let unsafeMutableRawPointer): | ||
| self = .pointer(unsafeMutableRawPointer) | ||
| } | ||
| } | ||
|
|
||
| var description: String { | ||
| switch self { | ||
| case .data(let data): | ||
| "data: \(data)" | ||
| case .bytes(let contiguousBytes): | ||
| "bytes: \(contiguousBytes)" | ||
| case .byteBuffer(let internalByteBuffer): | ||
| "byteBuffer: \(internalByteBuffer)" | ||
| case .array(let array): | ||
| "array: \(array)" | ||
| case .pointer(let unsafeMutableRawPointer): | ||
| "pointer: \(unsafeMutableRawPointer)" | ||
| } | ||
| } | ||
| } | ||
| #else | ||
| @usableFromInline | ||
| @frozen enum Blob { | ||
| #if !os(WASI) | ||
| case data(Data) | ||
| case bytes(ContiguousBytes) | ||
| #endif | ||
|
|
||
| case byteBuffer(_InternalByteBuffer) | ||
| case array([UInt8]) | ||
| case pointer(UnsafeMutableRawPointer) | ||
|
|
||
| var description: String { | ||
| switch self { | ||
| case .data(let data): | ||
| return "data: \(data)" | ||
| case .bytes(let contiguousBytes): | ||
| return "bytes: \(contiguousBytes)" | ||
| case .byteBuffer(let internalByteBuffer): | ||
| return "byteBuffer: \(internalByteBuffer)" | ||
| case .array(let array): | ||
| return "array: \(array)" | ||
| case .pointer(let unsafeMutableRawPointer): | ||
| return "pointer: \(unsafeMutableRawPointer)" | ||
| } | ||
| } | ||
| } | ||
| #endif | ||
|
|
||
| /// This storage doesn't own the memory, therefore, we won't deallocate on deinit. | ||
| private let isOwned: Bool | ||
| /// Capacity of UInt8 the buffer can hold | ||
| private let capacity: Int | ||
| /// Retained blob of data that requires the storage to retain a pointer to. | ||
| @usableFromInline | ||
| var retainedBlob: Blob | ||
| let retainedBlob: Blob | ||
|
|
||
| @usableFromInline | ||
| init(count: Int) { | ||
|
|
@@ -56,12 +115,21 @@ public struct ByteBuffer { | |
| isOwned = true | ||
| } | ||
|
|
||
| #if compiler(>=6.0) | ||
| @usableFromInline | ||
| init(blob: borrowing Blob, capacity count: Int) { | ||
| capacity = count | ||
| retainedBlob = .init(blob) | ||
| isOwned = false | ||
| } | ||
| #else | ||
| @usableFromInline | ||
| init(blob: Blob, capacity count: Int) { | ||
| capacity = count | ||
| retainedBlob = blob | ||
| isOwned = false | ||
| } | ||
| #endif | ||
|
|
||
| deinit { | ||
| guard isOwned else { return } | ||
|
|
@@ -150,6 +218,7 @@ public struct ByteBuffer { | |
|
|
||
| @discardableResult | ||
| @inline(__always) | ||
| @inlinable | ||
| func readWithUnsafeRawPointer<T>( | ||
| position: Int, | ||
| _ body: (UnsafeRawPointer) throws -> T) rethrows -> T | ||
|
|
@@ -276,6 +345,18 @@ public struct ByteBuffer { | |
| /// - memory: Current memory of the buffer | ||
| /// - count: count of bytes | ||
| /// - removeBytes: Removes a number of bytes from the current size | ||
| #if compiler(>=6.0) | ||
| @inline(__always) | ||
| init( | ||
| blob: borrowing Storage.Blob, | ||
| count: Int, | ||
| removing removeBytes: Int) | ||
| { | ||
| _storage = Storage(blob: blob, capacity: count) | ||
| _readerIndex = removeBytes | ||
| capacity = count | ||
| } | ||
| #else | ||
|
Comment on lines
+348
to
+359
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Im wondering if we can reduce the amount of
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I can wait for #8983 and remove all swift>=6.0 annotations all together. |
||
| @inline(__always) | ||
| init( | ||
| blob: Storage.Blob, | ||
|
|
@@ -286,6 +367,7 @@ public struct ByteBuffer { | |
| _readerIndex = removeBytes | ||
| capacity = count | ||
| } | ||
| #endif | ||
|
|
||
| /// Write stores an object into the buffer directly or indirectly. | ||
| /// | ||
|
|
@@ -317,13 +399,25 @@ public struct ByteBuffer { | |
| /// - Parameters: | ||
| /// - def: Type of the object | ||
| /// - position: the index of the object in the buffer | ||
| #if compiler(>=6.0) | ||
| @inline(__always) | ||
| @inlinable | ||
| public func read<T: BitwiseCopyable>(def: T.Type, position: Int) -> T { | ||
| _storage.readWithUnsafeRawPointer(position: position) { | ||
| $0.bindMemory(to: T.self, capacity: 1) | ||
| .pointee | ||
| } | ||
| } | ||
| #else | ||
| @inline(__always) | ||
| @inlinable | ||
| public func read<T>(def: T.Type, position: Int) -> T { | ||
| _storage.readWithUnsafeRawPointer(position: position) { | ||
| $0.bindMemory(to: T.self, capacity: 1) | ||
| .pointee | ||
| } | ||
| } | ||
| #endif | ||
|
|
||
| /// Reads a slice from the memory assuming a type of T | ||
| /// - Parameters: | ||
|
|
@@ -412,7 +506,7 @@ public struct ByteBuffer { | |
| /// - Parameter removeBytes: the amount of bytes to remove from the current Size | ||
| @inline(__always) | ||
| public func duplicate(removing removeBytes: Int = 0) -> ByteBuffer { | ||
| assert(removeBytes > 0, "Can NOT remove negative bytes") | ||
| assert(removeBytes >= 0, "Can NOT remove negative bytes") | ||
| assert( | ||
| removeBytes < capacity, | ||
| "Can NOT remove more bytes than the ones allocated") | ||
|
|
@@ -464,8 +558,9 @@ public struct ByteBuffer { | |
| extension ByteBuffer: CustomDebugStringConvertible { | ||
|
|
||
| public var debugDescription: String { | ||
| """ | ||
| buffer located at: \(_storage.retainedBlob), | ||
| let blobDescription = _storage.retainedBlob.description | ||
| return """ | ||
| buffer located at: \(blobDescription), | ||
| with capacity of \(capacity), | ||
| { writtenSize: \(_readerIndex), readerSize: \(reader), | ||
| size: \(size) } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -47,7 +47,8 @@ public struct FlatBufferBuilder { | |
| /// A check to see if finish(::) was ever called to retreive data object | ||
| private var finished = false | ||
| /// A check to see if the buffer should serialize Default values | ||
| private var serializeDefaults: Bool | ||
| @usableFromInline | ||
| var serializeDefaults: Bool | ||
|
Comment on lines
+50
to
+51
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder, can this simply be a |
||
|
|
||
| /// Current alignment for the buffer | ||
| var _minAlignment: Int = 0 { | ||
|
|
@@ -756,6 +757,7 @@ public struct FlatBufferBuilder { | |
| /// - offset: ``Offset`` of another object to be written | ||
| /// - position: The predefined position of the object | ||
| @inline(__always) | ||
| @inlinable | ||
| mutating public func add(offset: Offset, at position: VOffset) { | ||
| if offset.isEmpty { return } | ||
| add(element: refer(to: offset.o), def: 0, at: position) | ||
|
|
@@ -794,6 +796,7 @@ public struct FlatBufferBuilder { | |
| /// - def: Default value for that element | ||
| /// - position: The predefined position of the element | ||
| @inline(__always) | ||
| @inlinable | ||
| mutating public func add<T: Scalar>( | ||
| element: T, | ||
| def: T, | ||
|
|
@@ -813,6 +816,7 @@ public struct FlatBufferBuilder { | |
| /// - element: Optional element of type scalar | ||
| /// - position: The predefined position of the element | ||
| @inline(__always) | ||
| @inlinable | ||
| mutating public func add<T: Scalar>(element: T?, at position: VOffset) { | ||
| guard let element = element else { return } | ||
| track(offset: push(element: element), at: position) | ||
|
|
@@ -825,6 +829,7 @@ public struct FlatBufferBuilder { | |
| /// - Parameter element: Element to insert | ||
| /// - returns: position of the Element | ||
| @inline(__always) | ||
| @inlinable | ||
| @discardableResult | ||
| mutating public func push<T: Scalar>(element: T) -> UOffset { | ||
| let size = MemoryLayout<T>.size | ||
|
|
@@ -835,10 +840,19 @@ public struct FlatBufferBuilder { | |
| return _bb.size | ||
| } | ||
|
|
||
| #if compiler(>=6.0) | ||
| @inline(__always) | ||
| @inlinable | ||
| public func read<T: BitwiseCopyable>(def: T.Type, position: Int) -> T { | ||
| _bb.read(def: def, position: position) | ||
| } | ||
| #else | ||
| @inline(__always) | ||
| @inlinable | ||
| public func read<T>(def: T.Type, position: Int) -> T { | ||
| _bb.read(def: def, position: position) | ||
| } | ||
| #endif | ||
| } | ||
|
|
||
| extension FlatBufferBuilder: CustomDebugStringConvertible { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
requires OS not wasm flag