A struct of arrays implementation in pure Swift.
Add to your package.swift
in the dependencies:
.package(url: "https://github.com/jomy10/swift-soa", .branch("master"))
Add to your Package.swift
in a target's dependency:
.package(name: "SoA", package: "soa-swift")
Initialize a Soa
instance with an initial capacity of 32 elements.
let soa = SoA(
Fields()
.field(Int.self)
.field(String.self)
)
When you want to add more elements than the current capacity of the SoA
(soa.capacity
), you
need to resize it first.
soa.capacity = soa.capacity * 2
When adding elements, you should always make sure you're not adding more elements than the capacity allows.
var soa = SoA(
Fields().field(Int.self)
)
let idx = 5 // element 5 in array 0 (field 0)
if idx < soa.capacity {
soa.set(0, at: idx, 69)
} else {
// resize first
}
soa.get(0, at: idx)
If you want to add types like classes to the struct of array, you will have to convert them to a pointer first.
For String types, you can use the designated string functions.
soa.get(1, at: 0) as String?
soa.set(1, at: 0, str: "Hello world")
For pointers:
soa.getBufPtr(1, at: 0)
// set pointer and deallocate previous managed pointer at the specified index
soa.set(1, at: 0, ptr: myPtr)
// set pointer, deallocate previous managed pointer at the specified index,
// and add this pointer to be managed by the `SoA`
soa.set(1, at: 0, managedPtr: myPtr)
// set pointer without trying to deallocate the previous pointer
soa.setUnmanaged(1, at: 0, ptr: myPtr)
Strings will always use the soa.set(Int, at: Int, managedPtr: UnsafeRawBufferPointer)
.
Using the set
method to mutate elements in a loop can be slow, use slice
instead.
Primitive types
// Slice field 0
soa.slice(0) { (slice: UnsafeSoASlice<Int>) in
var slice = slice
slice[0] = 5
print(slice[0])
}
Pointers
soa.slice(0) { (slice: UnsafeSoASliceBufPtr<MyType>) in
var slice = slice
// set pointer and deallocate previous
slice[0] = otherPointer
// set pointer and deallocate previous and manage this one
slice[managedPtr: 0] = otherPointer
// set pointer without trying to deallocate
slice[unmanaged: 0] = otherPointer
print(slice[0])
}
Strings
soa.slice(0) { (slice: UnsafeSoAString) in
var slice = slice
slice[0] = "Hello!"
print(slice[0])
}
The library is intentionally low-level as it is meant as a "core" library. The user of the library is encouraged to build their own abstraction layer on top of this library.
swift test
./bench.sh
The library is licensed under the GNU LGPL3.0.