Skip to content

Commit

Permalink
Adds Nativestructs pointer push into ByteBuffer
Browse files Browse the repository at this point in the history
Updates benchmarks & cleanup

Adds native struct vector tests
  • Loading branch information
mustiikhalil committed Nov 20, 2023
1 parent b08abbb commit 9609ff5
Show file tree
Hide file tree
Showing 9 changed files with 221 additions and 118 deletions.
18 changes: 16 additions & 2 deletions swift/Sources/FlatBuffers/ByteBuffer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,20 @@ public struct ByteBuffer {
}
}

/// Adds an array of type Scalar to the buffer memory
/// - Parameter elements: An array of Scalars
@inline(__always)
@usableFromInline
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)
self._writerSize = self._writerSize &+ ptr.count
}
}

/// Adds a `ContiguousBytes` to buffer memory
/// - Parameter value: bytes to copy
#if swift(>=5.0) && !os(WASI)
Expand All @@ -248,8 +262,8 @@ public struct ByteBuffer {
ensureSpace(size: ptr.count)
memcpy(
_storage.memory.advanced(by: writerIndex &- ptr.count),
UnsafeRawPointer(ptr.baseAddress!),
ptr.count)
UnsafeRawPointer(ptr.baseAddress!),
ptr.count)
self._writerSize = self._writerSize &+ ptr.count
}
}
Expand Down
4 changes: 1 addition & 3 deletions swift/Sources/FlatBuffers/FlatBufferBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -623,9 +623,7 @@ public struct FlatBufferBuilder {
startVector(
structs.count * MemoryLayout<T>.size,
elementSize: MemoryLayout<T>.alignment)
for i in structs.reversed() {
_ = create(struct: i)
}
_bb.push(elements: structs)
return endVector(len: structs.count)
}

Expand Down
4 changes: 3 additions & 1 deletion swift/Sources/FlatBuffers/Verifiable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,9 @@ public enum Vector<U, S>: Verifiable where U: Verifiable, S: Verifiable {
let range = try verifyRange(&verifier, at: position, of: UOffset.self)
for index in stride(
from: range.start,
to: Int(clamping: range.start &+ (range.count &* MemoryLayout<Int32>.size)),
to: Int(
clamping: range
.start &+ (range.count &* MemoryLayout<Int32>.size)),
by: MemoryLayout<UOffset>.size)
{
try U.verify(&verifier, at: index, of: U.self)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
///*
// * Copyright 2023 Google Inc. All rights reserved.
// *
// * Licensed under the Apache License, Version 2.0 (the "License");
// * you may not use this file except in compliance with the License.
// * You may obtain a copy of the License at
// *
// * http://www.apache.org/licenses/LICENSE-2.0
// *
// * Unless required by applicable law or agreed to in writing, software
// * distributed under the License is distributed on an "AS IS" BASIS,
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// * See the License for the specific language governing permissions and
// * limitations under the License.
// */

import Benchmark
import CoreFoundation
import FlatBuffers

@usableFromInline
struct AA: NativeStruct {
public init(a: Double, b: Double) {
self.a = a
self.b = b
}
var a: Double
var b: Double
}

let benchmarks = {
let ints: [Int] = Array(repeating: 42, count: 100)
let bytes: [UInt8] = Array(repeating: 42, count: 100)
let str = (0...99).map { _ -> String in "x" }.joined()
let array: [AA] = [
AA(a: 2.4, b: 2.4),
AA(a: 2.4, b: 2.4),
AA(a: 2.4, b: 2.4),
AA(a: 2.4, b: 2.4),
AA(a: 2.4, b: 2.4),
]

Benchmark("Allocating") { benchmark in
for i in benchmark.scaledIterations {
var fb = FlatBufferBuilder(initialSize: 1_024_000_000)
}
}

Benchmark("Strings 10") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1<<20)
for i in benchmark.scaledIterations {
benchmark.startMeasurement()
for _ in 0..<1_000_000 {
_ = fb.create(string: "foobarbaz")
}
benchmark.stopMeasurement()
fb.clear()
}
}

Benchmark("Strings 100") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1<<20)
for i in benchmark.scaledIterations {
benchmark.startMeasurement()
for _ in 0..<1_000_000 {
_ = fb.create(string: str)
}
benchmark.stopMeasurement()
fb.clear()
}
}

Benchmark("Vector 100 Ints") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1<<20)
benchmark.startMeasurement()
for i in benchmark.scaledIterations {
benchmark.startMeasurement()
for _ in 0..<1_000_000 {
_ = fb.createVector(ints)
}
benchmark.stopMeasurement()
fb.clear()
}
}

Benchmark("Vector 100 Bytes") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1<<20)
for i in benchmark.scaledIterations {
benchmark.startMeasurement()
for _ in 0..<1_000_000 {
_ = fb.createVector(bytes)
}
benchmark.stopMeasurement()
fb.clear()
}
}

Benchmark("Vector 100 ContiguousBytes") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1<<20)
for i in benchmark.scaledIterations {
benchmark.startMeasurement()
for _ in 0..<1_000_000 {
_ = fb.createVector(bytes: bytes)
}
benchmark.stopMeasurement()
fb.clear()
}
}

Benchmark("FlatBufferBuilder Add") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1024 * 1024 * 32)
for _ in benchmark.scaledIterations {
benchmark.startMeasurement()
for _ in 0..<1_000_000 {
let off = fb.create(string: "T")
let s = fb.startTable(with: 4)
fb.add(element: 3.2, def: 0, at: 2)
fb.add(element: 4.2, def: 0, at: 4)
fb.add(element: 5.2, def: 0, at: 6)
fb.add(offset: off, at: 8)
_ = fb.endTable(at: s)
}
benchmark.stopMeasurement()
fb.clear()
}
}

Benchmark("structs") { benchmark in
let structCount = 1_000_000

let rawSize = ((16 * 5) * structCount) / 1024

var fb = FlatBufferBuilder(initialSize: Int32(rawSize * 1600))

for _ in benchmark.scaledIterations {
benchmark.startMeasurement()
var offsets: [Offset] = []
for _ in 0..<structCount {
let vector = fb.createVector(
ofStructs: array)
let start = fb.startTable(with: 1)
fb.add(offset: vector, at: 4)
offsets.append(Offset(offset: fb.endTable(at: start)))
}
let vector = fb.createVector(ofOffsets: offsets)
let start = fb.startTable(with: 1)
fb.add(offset: vector, at: 4)
let root = Offset(offset: fb.endTable(at: start))
fb.finish(offset: root)
benchmark.stopMeasurement()
fb.clear()
}
}
}
22 changes: 15 additions & 7 deletions tests/swift/benchmarks/Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.1
// swift-tools-version:5.8
/*
* Copyright 2020 Google Inc. All rights reserved.
*
Expand All @@ -20,15 +20,23 @@ import PackageDescription
let package = Package(
name: "benchmarks",
platforms: [
.macOS(.v10_14),
.macOS(.v13),
],
dependencies: [
.package(path: "../../.."),
.package(url: "https://github.com/google/swift-benchmark", from: "0.1.0"),
.package(
url: "https://github.com/ordo-one/package-benchmark",
from: "1.12.0"),
],
targets: [
.target(
name: "benchmarks",
dependencies: ["FlatBuffers",
.product(name: "Benchmark", package: "swift-benchmark")]),
.executableTarget(
name: "FlatbuffersBenchmarks",
dependencies: [
.product(name: "FlatBuffers", package: "flatbuffers"),
.product(name: "Benchmark", package: "package-benchmark"),
],
path: "Benchmarks/FlatbuffersBenchmarks",
plugins: [
.plugin(name: "BenchmarkPlugin", package: "package-benchmark"),
]),
])
9 changes: 9 additions & 0 deletions tests/swift/benchmarks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Benchmarks

To open the benchmarks in xcode use:

`open --env BENCHMARK_DISABLE_JEMALLOC=true Package.swift`

or running them directly within terminal using:

`swift package benchmark`
102 changes: 0 additions & 102 deletions tests/swift/benchmarks/Sources/benchmarks/main.swift

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ final class FlatBuffersNanInfTests: XCTestCase {
let data = try encoder.encode(reader)
let decoder = JSONDecoder()
decoder.nonConformingFloatDecodingStrategy = .convertFromString(
positiveInfinity: "inf",
negativeInfinity: "-inf",
nan: "nan")
positiveInfinity: "inf",
negativeInfinity: "-inf",
nan: "nan")
decoder.keyDecodingStrategy = .convertFromSnakeCase
let value = try decoder.decode(Test.self, from: data)
XCTAssertEqual(value.value, 100)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,26 @@ final class FlatBuffersVectors: XCTestCase {
// swiftformat:enable all
}

func testCreateStructArray() {
struct Vec: NativeStruct {
let x, y, z: Float32
}
let vector: [Vec] = [
Vec(x: 1, y: 2, z: 3),
Vec(x: 4, y: 5, z: 6),
Vec(x: 7, y: 8, z: 9),
]
var b = FlatBufferBuilder(initialSize: 100)
let o = b.createVector(ofStructs: vector)
b.finish(offset: o)
vector.withUnsafeBytes { pointer in
print(Array(pointer))
}
// swiftformat:disable all
XCTAssertEqual(b.sizedByteArray, [4, 0, 0, 0, 3, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 128, 64, 0, 0, 160, 64, 0, 0, 192, 64, 0, 0, 224, 64, 0, 0, 0, 65, 0, 0, 16, 65])
// swiftformat:enable all
}

func testCreateEmptyIntArray() {
let numbers: [Int32] = []
var b = FlatBufferBuilder(initialSize: 20)
Expand Down

0 comments on commit 9609ff5

Please sign in to comment.