Fix sparse component set performance
This commit is contained in:
parent
a559387891
commit
4ada634130
|
|
@ -7,43 +7,34 @@
|
|||
|
||||
public class SparseComponentSet {
|
||||
public typealias Element = Component
|
||||
public let chunkSize: Int = 4096
|
||||
fileprivate typealias ComponentIdx = Int
|
||||
fileprivate var size: Int = 0
|
||||
|
||||
fileprivate class Pair {
|
||||
let key: EntityIndex
|
||||
let value: Element
|
||||
init(key: EntityIndex, value: Element) {
|
||||
self.key = key
|
||||
self.value = value
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate var dense: ContiguousArray<Pair?>
|
||||
fileprivate var sparse: [EntityIndex: ComponentIdx]
|
||||
fileprivate typealias Pair = (key: EntityIndex, value: Element)
|
||||
|
||||
public init() {
|
||||
dense = ContiguousArray<Pair?>()
|
||||
dense.reserveCapacity(chunkSize)
|
||||
sparse = [EntityIndex: ComponentIdx].init(minimumCapacity: chunkSize)
|
||||
sparse = [EntityIndex: ComponentIdx]()
|
||||
}
|
||||
|
||||
deinit {
|
||||
clear()
|
||||
}
|
||||
|
||||
public var count: Int { return size }
|
||||
internal var capacitySparse: Int { return sparse.count }
|
||||
internal var capacityDense: Int { return dense.count }
|
||||
internal var capacitySparse: Int { return sparse.capacity }
|
||||
internal var capacityDense: Int { return dense.capacity }
|
||||
|
||||
public func contains(_ entityIdx: EntityIndex ) -> Bool {
|
||||
guard let compIdx: ComponentIdx = sparse[entityIdx] else { return false }
|
||||
return compIdx < count && dense[compIdx] != nil
|
||||
return sparse[entityIdx] != nil &&
|
||||
sparse[entityIdx]! < count &&
|
||||
dense[sparse[entityIdx]!] != nil
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
public func add(_ element: Element, with entityIdx: EntityIndex ) -> Bool {
|
||||
if contains(entityIdx) { return false }
|
||||
if needsToGrow(entityIdx) {
|
||||
grow(including: entityIdx)
|
||||
}
|
||||
sparse[entityIdx] = count
|
||||
let entry: Pair = Pair(key: entityIdx, value: element)
|
||||
dense.append(entry)
|
||||
|
|
@ -52,52 +43,39 @@ public class SparseComponentSet {
|
|||
}
|
||||
|
||||
public func get(at entityIdx: EntityIndex) -> Element? {
|
||||
guard let compIdx: ComponentIdx = sparse[entityIdx] else { return nil }
|
||||
return dense[compIdx]!.value
|
||||
guard contains(entityIdx) else { return nil }
|
||||
return dense[sparse[entityIdx]!]!.value
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
public func remove(_ entityIdx: EntityIndex ) -> Element? {
|
||||
guard let compIdx: ComponentIdx = sparse[entityIdx] else { return nil }
|
||||
let last: Int = count-1
|
||||
dense.swapAt(compIdx, last)
|
||||
guard contains(entityIdx) else { return nil }
|
||||
let compIdx: ComponentIdx = sparse[entityIdx]!
|
||||
let lastIdx: ComponentIdx = count-1
|
||||
dense.swapAt(compIdx, lastIdx)
|
||||
sparse[entityIdx] = nil
|
||||
let swapped: Pair = dense[compIdx]!
|
||||
sparse[swapped.key] = compIdx
|
||||
let removed: Pair = dense.popLast()!!
|
||||
size -= 1
|
||||
if size == 0 {
|
||||
clear(keepingCapacity: false)
|
||||
}
|
||||
return removed.value
|
||||
}
|
||||
|
||||
public func clear(keepingCapacity: Bool = false) {
|
||||
size = 0
|
||||
dense.removeAll(keepingCapacity: keepingCapacity)
|
||||
sparse.removeAll(keepingCapacity: keepingCapacity)
|
||||
}
|
||||
|
||||
fileprivate func needsToGrow(_ index: Int) -> Bool {
|
||||
return index > count - 1
|
||||
}
|
||||
|
||||
fileprivate func grow(including index: Int) {
|
||||
let newCapacity: Int = nearest(to: index)
|
||||
//let newCount: Int = newCapacity-count
|
||||
dense.reserveCapacity(newCapacity)
|
||||
/*for _ in 0..<newCount {
|
||||
dense.append(nil)
|
||||
}*/
|
||||
}
|
||||
|
||||
fileprivate func nearest(to index: Int) -> Int {
|
||||
let delta = Float(index) / Float(chunkSize)
|
||||
let multiplier = Int(delta) + 1
|
||||
return multiplier * chunkSize
|
||||
}
|
||||
}
|
||||
|
||||
extension SparseComponentSet: Sequence {
|
||||
|
||||
public func makeIterator() -> AnyIterator<Element> {
|
||||
var iterator = dense.makeIterator()
|
||||
|
||||
return AnyIterator<Element> {
|
||||
iterator.next()??.value
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue