mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-01 19:58:15 +00:00
[Swift] Improves vectors performance & arrays within lib (#8415)
* Improves vectors performance and adds a benchmark to vectors of offsets in swift Improves performance for all arrays and for loops Uses a tuple instead of allocating a struct each time we start iterating over fieldloc Updates benchmark library * Fixing swift Wasm ci
This commit is contained in:
@@ -251,7 +251,7 @@ public struct ByteBuffer {
|
||||
ensureSpace(size: ptr.count)
|
||||
memcpy(
|
||||
_storage.memory.advanced(by: writerIndex &- ptr.count),
|
||||
UnsafeRawPointer(ptr.baseAddress!),
|
||||
ptr.baseAddress!,
|
||||
ptr.count)
|
||||
_writerSize = _writerSize &+ ptr.count
|
||||
}
|
||||
@@ -264,9 +264,10 @@ public struct ByteBuffer {
|
||||
mutating func push<T: NativeStruct>(elements: [T]) {
|
||||
elements.withUnsafeBytes { ptr in
|
||||
ensureSpace(size: ptr.count)
|
||||
_storage.memory
|
||||
.advanced(by: writerIndex &- ptr.count)
|
||||
.copyMemory(from: ptr.baseAddress!, byteCount: ptr.count)
|
||||
memcpy(
|
||||
_storage.memory.advanced(by: writerIndex &- ptr.count),
|
||||
ptr.baseAddress!,
|
||||
ptr.count)
|
||||
_writerSize = _writerSize &+ ptr.count
|
||||
}
|
||||
}
|
||||
@@ -281,7 +282,7 @@ public struct ByteBuffer {
|
||||
ensureSpace(size: ptr.count)
|
||||
memcpy(
|
||||
_storage.memory.advanced(by: writerIndex &- ptr.count),
|
||||
UnsafeRawPointer(ptr.baseAddress!),
|
||||
ptr.baseAddress!,
|
||||
ptr.count)
|
||||
_writerSize = _writerSize &+ ptr.count
|
||||
}
|
||||
@@ -296,11 +297,10 @@ public struct ByteBuffer {
|
||||
@inline(__always)
|
||||
mutating func push<T: NativeStruct>(struct value: T, size: Int) {
|
||||
ensureSpace(size: size)
|
||||
var v = value
|
||||
withUnsafeBytes(of: &v) {
|
||||
withUnsafePointer(to: value) {
|
||||
memcpy(
|
||||
_storage.memory.advanced(by: writerIndex &- size),
|
||||
$0.baseAddress!,
|
||||
$0,
|
||||
size)
|
||||
_writerSize = _writerSize &+ size
|
||||
}
|
||||
@@ -314,11 +314,10 @@ public struct ByteBuffer {
|
||||
@usableFromInline
|
||||
mutating func push<T: Scalar>(value: T, len: Int) {
|
||||
ensureSpace(size: len)
|
||||
var v = value
|
||||
withUnsafeBytes(of: &v) {
|
||||
withUnsafePointer(to: value) {
|
||||
memcpy(
|
||||
_storage.memory.advanced(by: writerIndex &- len),
|
||||
$0.baseAddress!,
|
||||
$0,
|
||||
len)
|
||||
_writerSize = _writerSize &+ len
|
||||
}
|
||||
@@ -355,7 +354,7 @@ public struct ByteBuffer {
|
||||
{
|
||||
memcpy(
|
||||
_storage.memory.advanced(by: writerIndex &- len),
|
||||
UnsafeRawPointer(bytes.baseAddress!),
|
||||
bytes.baseAddress!,
|
||||
len)
|
||||
_writerSize = _writerSize &+ len
|
||||
return true
|
||||
@@ -377,7 +376,12 @@ public struct ByteBuffer {
|
||||
}
|
||||
assert(index < _storage.capacity, "Write index is out of writing bound")
|
||||
assert(index >= 0, "Writer index should be above zero")
|
||||
_storage.memory.storeBytes(of: value, toByteOffset: index, as: T.self)
|
||||
withUnsafePointer(to: value) {
|
||||
memcpy(
|
||||
_storage.memory.advanced(by: index),
|
||||
$0,
|
||||
MemoryLayout<T>.size)
|
||||
}
|
||||
}
|
||||
|
||||
/// Makes sure that buffer has enouch space for each of the objects that will be written into it
|
||||
|
||||
@@ -146,12 +146,12 @@ public struct FlatBufferBuilder {
|
||||
/// by the generated code*
|
||||
@inline(__always)
|
||||
mutating public func require(table: Offset, fields: [Int32]) {
|
||||
for field in fields {
|
||||
for index in stride(from: 0, to: fields.count, by: 1) {
|
||||
let start = _bb.capacity &- Int(table.o)
|
||||
let startTable = start &- Int(_bb.read(def: Int32.self, position: start))
|
||||
let isOkay = _bb.read(
|
||||
def: VOffset.self,
|
||||
position: startTable &+ Int(field)) != 0
|
||||
position: startTable &+ Int(fields[index])) != 0
|
||||
assert(isOkay, "Flatbuffers requires the following field")
|
||||
}
|
||||
}
|
||||
@@ -285,13 +285,13 @@ public struct FlatBufferBuilder {
|
||||
let vt2 = _bb.memory.advanced(by: _bb.writerIndex)
|
||||
let len2 = vt2.load(fromByteOffset: 0, as: Int16.self)
|
||||
|
||||
for table in _vtables {
|
||||
let position = _bb.capacity &- Int(table)
|
||||
for index in stride(from: 0, to: _vtables.count, by: 1) {
|
||||
let position = _bb.capacity &- Int(_vtables[index])
|
||||
let vt1 = _bb.memory.advanced(by: position)
|
||||
let len1 = _bb.read(def: Int16.self, position: position)
|
||||
if len2 != len1 || 0 != memcmp(vt1, vt2, Int(len2)) { continue }
|
||||
|
||||
isAlreadyAdded = Int(table)
|
||||
isAlreadyAdded = Int(_vtables[index])
|
||||
break
|
||||
}
|
||||
|
||||
@@ -380,7 +380,7 @@ public struct FlatBufferBuilder {
|
||||
@inline(__always)
|
||||
@usableFromInline
|
||||
mutating internal func track(offset: UOffset, at position: VOffset) {
|
||||
_vtableStorage.add(loc: FieldLoc(offset: offset, position: position))
|
||||
_vtableStorage.add(loc: (offset: offset, position: position))
|
||||
}
|
||||
|
||||
// MARK: - Inserting Vectors
|
||||
@@ -524,8 +524,8 @@ public struct FlatBufferBuilder {
|
||||
{
|
||||
let size = size
|
||||
startVector(size, elementSize: T.byteSize)
|
||||
for e in elements.reversed() {
|
||||
_bb.push(value: e.value, len: T.byteSize)
|
||||
for index in stride(from: elements.count, to: 0, by: -1) {
|
||||
_bb.push(value: elements[index &- 1].value, len: T.byteSize)
|
||||
}
|
||||
return endVector(len: size)
|
||||
}
|
||||
@@ -569,8 +569,8 @@ public struct FlatBufferBuilder {
|
||||
len: Int) -> Offset
|
||||
{
|
||||
startVector(len, elementSize: MemoryLayout<Offset>.size)
|
||||
for o in offsets.reversed() {
|
||||
push(element: o)
|
||||
for index in stride(from: offsets.count, to: 0, by: -1) {
|
||||
push(element: offsets[index &- 1])
|
||||
}
|
||||
return endVector(len: len)
|
||||
}
|
||||
@@ -593,8 +593,8 @@ public struct FlatBufferBuilder {
|
||||
@inline(__always)
|
||||
mutating public func createVector(ofStrings str: [String]) -> Offset {
|
||||
var offsets: [Offset] = []
|
||||
for s in str {
|
||||
offsets.append(create(string: s))
|
||||
for index in stride(from: 0, to: str.count, by: 1) {
|
||||
offsets.append(create(string: str[index]))
|
||||
}
|
||||
return createVector(ofOffsets: offsets)
|
||||
}
|
||||
@@ -646,9 +646,8 @@ public struct FlatBufferBuilder {
|
||||
struct s: T, position: VOffset) -> Offset
|
||||
{
|
||||
let offset = create(struct: s)
|
||||
_vtableStorage.add(loc: FieldLoc(
|
||||
offset: _bb.size,
|
||||
position: VOffset(position)))
|
||||
_vtableStorage.add(
|
||||
loc: (offset: _bb.size, position: VOffset(position)))
|
||||
return offset
|
||||
}
|
||||
|
||||
@@ -837,6 +836,8 @@ extension FlatBufferBuilder: CustomDebugStringConvertible {
|
||||
"""
|
||||
}
|
||||
|
||||
typealias FieldLoc = (offset: UOffset, position: VOffset)
|
||||
|
||||
/// VTableStorage is a class to contain the VTable buffer that would be serialized into buffer
|
||||
@usableFromInline
|
||||
internal class VTableStorage {
|
||||
@@ -920,12 +921,5 @@ extension FlatBufferBuilder: CustomDebugStringConvertible {
|
||||
func load(at index: Int) -> FieldLoc {
|
||||
memory.load(fromByteOffset: index, as: FieldLoc.self)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal struct FieldLoc {
|
||||
var offset: UOffset
|
||||
var position: VOffset
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user