Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(ByteBuffer(assumingMemoryBound: memory, capacity: Int(oneGB)))
}
benchmark.stopMeasurement()
}

Benchmark("Clearing 1GB", configuration: singleConfiguration) { benchmark in
Expand All @@ -105,6 +106,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(fb.clear())
}
benchmark.stopMeasurement()
}

Benchmark("Strings 10") { benchmark in
Expand All @@ -113,6 +115,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(fb.create(string: str10))
}
benchmark.stopMeasurement()
}

Benchmark("Strings 100") { benchmark in
Expand All @@ -121,6 +124,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(fb.create(string: str100))
}
benchmark.stopMeasurement()
}

Benchmark("Vector 1 Bytes") { benchmark in
Expand All @@ -129,6 +133,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(fb.createVector(bytes: bytes))
}
benchmark.stopMeasurement()
}

Benchmark("Vector 1 Ints") { benchmark in
Expand All @@ -137,6 +142,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(fb.createVector(ints))
}
benchmark.stopMeasurement()
}

Benchmark("Vector 100 Ints") { benchmark in
Expand All @@ -145,6 +151,7 @@ let benchmarks = {
for i in benchmark.scaledIterations {
blackHole(fb.createVector(ints))
}
benchmark.stopMeasurement()
}

Benchmark("Vector 100 Bytes") { benchmark in
Expand All @@ -153,6 +160,7 @@ let benchmarks = {
for i in benchmark.scaledIterations {
blackHole(fb.createVector(bytes))
}
benchmark.stopMeasurement()
}

Benchmark("Vector 100 ContiguousBytes") { benchmark in
Expand All @@ -161,6 +169,7 @@ let benchmarks = {
for i in benchmark.scaledIterations {
blackHole(fb.createVector(bytes: bytes))
}
benchmark.stopMeasurement()
}

Benchmark(
Expand All @@ -178,6 +187,7 @@ let benchmarks = {
fb.add(offset: off, at: 8)
blackHole(fb.endTable(at: s))
}
benchmark.stopMeasurement()
}

Benchmark(
Expand All @@ -190,6 +200,7 @@ let benchmarks = {
let s = fb.startTable(with: 4)
blackHole(fb.endTable(at: s))
}
benchmark.stopMeasurement()
}

Benchmark("Struct") { benchmark in
Expand All @@ -198,6 +209,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(fb.create(struct: array.first!))
}
benchmark.stopMeasurement()
}

Benchmark("Structs") { benchmark in
Expand All @@ -219,6 +231,7 @@ let benchmarks = {
fb.add(offset: vector, at: 4)
let root = Offset(offset: fb.endTable(at: start))
blackHole(fb.finish(offset: root))
benchmark.stopMeasurement()
}

Benchmark("Vector of Offsets") { benchmark in
Expand All @@ -239,12 +252,15 @@ let benchmarks = {
fb.add(offset: off, at: 2)
blackHole(fb.endTable(at: s))
}
benchmark.stopMeasurement()
}

Benchmark("Reading Doubles") { benchmark in
let byteBuffer = ByteBuffer(data: data)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
blackHole(byteBuffer.read(def: Double.self, position: 0))
}
benchmark.stopMeasurement()
}
}
7 changes: 7 additions & 0 deletions swift/Sources/Common/Scalar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,17 @@ public let FileIdLength = 4
/// Protocol that All Scalars should conform to
///
/// Scalar is used to conform all the numbers that can be represented in a FlatBuffer. It's used to write/read from the buffer.
#if compiler(>=6.0)
public protocol Scalar: Equatable, BitwiseCopyable {
associatedtype NumericValue
var convertedEndian: NumericValue { get }
}
#else
public protocol Scalar: Equatable {
associatedtype NumericValue
var convertedEndian: NumericValue { get }
}
#endif

extension Scalar where Self: FixedWidthInteger {
/// Converts the value from BigEndian to LittleEndian
Expand Down
105 changes: 100 additions & 5 deletions swift/Sources/FlatBuffers/ByteBuffer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Comment on lines +43 to +46
Copy link
Copy Markdown
Collaborator

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

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) {
Expand All @@ -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 }
Expand Down Expand Up @@ -150,6 +218,7 @@ public struct ByteBuffer {

@discardableResult
@inline(__always)
@inlinable
func readWithUnsafeRawPointer<T>(
position: Int,
_ body: (UnsafeRawPointer) throws -> T) rethrows -> T
Expand Down Expand Up @@ -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
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im wondering if we can reduce the amount of #if compiler specially for language features that are available in 5.10, example: borrowing

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The 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,
Expand All @@ -286,6 +367,7 @@ public struct ByteBuffer {
_readerIndex = removeBytes
capacity = count
}
#endif

/// Write stores an object into the buffer directly or indirectly.
///
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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) }
Expand Down
16 changes: 15 additions & 1 deletion swift/Sources/FlatBuffers/FlatBufferBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder, can this simply be a let


/// Current alignment for the buffer
var _minAlignment: Int = 0 {
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand All @@ -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)
Expand All @@ -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
Expand All @@ -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 {
Expand Down
Loading
Loading