Stabelized API

This commit is contained in:
Christian Treffs 2017-10-09 16:06:57 +02:00
parent ec80d1ad1b
commit 6a045cd643
14 changed files with 543 additions and 268 deletions

View File

@ -8,19 +8,17 @@
public final class Entity: UniqueEntityIdentifiable { public final class Entity: UniqueEntityIdentifiable {
public let uei: UEI public let uei: UEI
fileprivate var eventDispatcher: EventDispatcher
fileprivate var componentMap: [UCT:Component] fileprivate var componentMap: [UCT:Component]
private init(uei: UEI) { init(uei: UEI, dispatcher: EventDispatcher) {
self.uei = uei self.uei = uei
self.eventDispatcher = dispatcher
componentMap = [UCT: Component]() componentMap = [UCT: Component]()
componentMap.reserveCapacity(2) componentMap.reserveCapacity(2)
}
convenience public init() {
let uei: UEI = UEI.next
self.init(uei: uei)
defer { defer {
notify(init: unownedRef) notifyInit()
} }
} }
@ -56,7 +54,7 @@ public extension Entity {
} }
// MARK: - push component(s) // MARK: - add/push component(s)
public extension Entity { public extension Entity {
@discardableResult @discardableResult
@ -70,6 +68,11 @@ public extension Entity {
return self return self
} }
@discardableResult
public final func add<C: Component>(component: C) -> Entity {
return push(component: component)
}
@discardableResult @discardableResult
public static func += <C: Component>(lhs: Entity, rhs: C) -> Entity { public static func += <C: Component>(lhs: Entity, rhs: C) -> Entity {
return lhs.push(component: rhs) return lhs.push(component: rhs)
@ -154,56 +157,85 @@ extension Entity {
final func destroy() { final func destroy() {
removeAll() removeAll()
UEI.free(uei) UEI.free(uei)
notify(destroyed: unownedRef) notifyDestoryed()
} }
} }
extension Entity: EventSender { extension Entity: EventDispatcher {
public func dispatch<E>(_ event: E) where E : Event {
private unowned var unownedRef: Entity { eventDispatcher.dispatch(event)
return self
} }
private func notify(init: Entity) { fileprivate func unowned(_ closure: @escaping (Entity) -> Void) {
dispatch(event: EntityCreated(entity: unownedRef)) #if DEBUG
let preActionCount: Int = retainCount(self)
#endif
let unownedClosure = { [unowned self] in
closure(self)
}
unownedClosure()
#if DEBUG
let postActionCount: Int = retainCount(self)
assert(postActionCount == preActionCount, "retain count missmatch [\(preActionCount)] -> [\(postActionCount)]")
#endif
}
private func notifyInit() {
unowned {
$0.dispatch(EntityCreated(entity: $0))
}
} }
private func notify<C: Component>(add component: C) { private func notify<C: Component>(add component: C) {
dispatch(event: ComponentAdded(component: component, to: unownedRef)) unowned {
$0.dispatch(ComponentAdded(component: component, to: $0))
}
} }
private func notify<C: Component>(update newComponent: C, previous previousComponent: C) { private func notify<C: Component>(update newComponent: C, previous previousComponent: C) {
dispatch(event: ComponentUpdated(component: newComponent, previous: previousComponent, at: unownedRef)) unowned {
$0.dispatch(ComponentUpdated(component: newComponent, previous: previousComponent, at: $0))
}
} }
private func notify<C: Component>(removed component: C) { private func notify<C: Component>(removed component: C) {
dispatch(event: ComponentRemoved(component: component, from: unownedRef)) unowned {
$0.dispatch(ComponentRemoved(component: component, from: $0))
}
} }
private func notify(removed component: Component) { private func notify(removed component: Component) {
dispatch(event: ComponentRemoved(component: component, from: unownedRef)) //unowned { /* this keeps a reference since we need it */
dispatch(ComponentRemoved(component: component, from: self))
//}
} }
private func notify(destroyed: Entity) { private func notifyDestoryed() {
dispatch(event: EntityDestroyed(entity: unownedRef)) //unowned {
//$0.dispatch(event: EntityDestroyed(entity: $0))
//TODO: here entity is already dead
//}
} }
} }
// MARK: - debugging and string representation // MARK: - debugging and string representation
/*
extension Entity: CustomStringConvertible, CustomDebugStringConvertible { extension Entity: CustomStringConvertible {
public var description: String { return "Entity\(stringifyLabel())[\(uid)]" }
public var debugDescription: String { fileprivate var componentsString: String {
let comps: String = self.componentMap.map { (_: ComponentType, comp: Component) in let compTypes: [String] = componentMap.map { String(describing: $0.value.uct.type) }
return comp.debugDescription return compTypes.joined(separator: ",")
}.joined(separator: ",")
return "\(self.description){ \(comps) }"
} }
public var description: String {
return "Entity[\(uei)][\(numComponents):\(componentsString)]"
}
} }
extension Entity: CustomPlaygroundQuickLookable { extension Entity: CustomPlaygroundQuickLookable {
public var customPlaygroundQuickLook: PlaygroundQuickLook { public var customPlaygroundQuickLook: PlaygroundQuickLook {
return .text(self.debugDescription) return .text(self.description)
} }
} }
*/

View File

@ -0,0 +1,45 @@
//
// EntityHub.swift
// FirebladeECS
//
// Created by Christian Treffs on 09.10.17.
//
class EntityHub: EventHandler {
weak var delegate: EventHub?
lazy var eventCenter: DefaultEventHub = { return DefaultEventHub() }()
private(set) var entites: [UEI:Entity] = [:]
init() {
self.delegate = eventCenter
subscribe(event: handleEntityCreated)
subscribe(event: handleComponentAdded)
}
deinit {
unsubscribe(event: handleEntityCreated)
unsubscribe(event: handleComponentAdded)
}
func createEntity() -> Entity {
let newEntity = Entity(uei: UEI.next, dispatcher: eventCenter)
// ^ dispatches entity creation event here ^
let prevEntity: Entity? = entites.updateValue(newEntity, forKey: newEntity.uei)
assert(prevEntity == nil)
return newEntity
}
}
// MARK: - event handler
extension EntityHub {
func handleEntityCreated(_ ec: EntityCreated) {
print(ec)
}
func handleComponentAdded(_ ca: ComponentAdded) {
print(ca)
}
}

View File

@ -1,174 +0,0 @@
//
// Event.swift
// FirebladeECS
//
// Created by Christian Treffs on 08.10.17.
//
protocol ECSEvent: UniqueEventIdentifiable { }
extension ECSEvent {
static var uet: UET { return UET(Self.self) }
var uet: UET { return Self.uet }
}
// MARK: - event dispachter protocol
protocol EventHandler: class {
func subscribe<E: ECSEvent>(event eventHandler: @escaping (E) -> Void)
func unsubscribe<E: ECSEvent>(event eventHandler: @escaping (E) -> Void)
unowned var listenerRef: EventHandler { get }
}
extension EventHandler {
unowned var listenerRef: EventHandler {
return self
}
/// Subscribe with an event handler closure to receive events of type T
///
/// - Parameter eventHandler: event handler closure
func subscribe<E: ECSEvent>(event eventHandler: @escaping (E) -> Void) {
EventHub.shared.add(listener: listenerRef, handler: eventHandler)
}
/// Unsubscribe from an event handler closure to stop receiving events of type T
///
/// - Parameter eventHandler: event handler closure
func unsubscribe<E: ECSEvent>(event eventHandler: @escaping (E) -> Void) {
EventHub.shared.remove(listener: listenerRef, handler: eventHandler)
}
}
protocol EventSender: class {
func dispatch<E: ECSEvent>(event: E)
}
extension EventSender {
/// Dispatch an event of type E
///
/// - Parameter event: event of type E
func dispatch<E: ECSEvent>(event: E) {
EventHub.shared.dispatch(event)
}
}
// MARK: - event hub central
fileprivate typealias EventListener = (weakRef: EventHandler, eventHandler: (ECSEvent) -> Void )
final class EventHub {
static let shared: EventHub = EventHub()
private var listeners: [UET: ContiguousArray<EventListener>] = [:]
private init() {}
}
extension ContiguousArray where Element == EventListener {
func index(is listenerRef: EventHandler) -> Int? {
return index { (eventListener: EventListener) -> Bool in
return eventListener.weakRef === listenerRef
}
}
}
extension EventHub {
private static func relayEvent<E: ECSEvent>(opaqueEvent: ECSEvent, eventHandler: @escaping (E) -> Void ) {
guard let typedEvent: E = opaqueEvent as? E else {
fatalError() // TODO: meaningful message
}
eventHandler(typedEvent)
}
final func add<E: ECSEvent>(listener listenerRef: EventHandler, handler: @escaping (E) -> Void) {
let eventListener: EventListener = (weakRef: listenerRef,
eventHandler: { EventHub.relayEvent(opaqueEvent: $0, eventHandler: handler) })
push(listener: eventListener, for: E.uet)
}
private func push(listener newListener: EventListener, `for` uet: UET) {
if listeners[uet] == nil {
listeners[uet] = []
listeners.reserveCapacity(1)
}
listeners[uet]?.append(newListener)
}
}
extension EventHub {
final func remove<E: ECSEvent>(listener listenerRef: EventHandler, handler: @escaping (E) -> Void) {
let uet: UET = E.uet
if let removeIdx: Int = listeners[uet]?.index(is: listenerRef) {
let removed = listeners[uet]?.remove(at: removeIdx)
assert(removed != nil)
}
}
}
extension EventHub {
final func dispatch<E: ECSEvent>(_ event: E) {
let uet: UET = E.uet
listeners[uet]?.forEach {
$0.eventHandler(event)
}
}
}
/*
extension EventHandler {
func subscribe<T: Event>(event eventHandler: @escaping (T) -> Void, syncOnQueue queue: WorkQueue)
func subscribe<T: Event>(event eventHandler: @escaping (T) -> Void, asyncOnQueue queue: WorkQueue)
}
extension EventSender {
/// Subscribe with a synchronous dispatched event handler closure to receive events of type T
///
/// - Parameters:
/// - eventHandler: event handler closure
/// - queue: queue to handle events
func subscribe<T: Event>(event eventHandler: @escaping (T) -> Void, syncOnQueue queue: WorkQueue) {
EventHub.shared.addSyncListener(owner: type(of: self), syncOnQueue: queue, handler: eventHandler)
}
/// Subscribe with an asynchronous dispatched event handler closure to receive events of type T
///
/// - Parameters:
/// - eventHandler: event handler closure
/// - queue: queue to handle events on
func subscribe<T: Event>(event eventHandler: @escaping (T) -> Void, asyncOnQueue queue: WorkQueue) {
EventHub.shared.addAsyncListener(owner: type(of: self), asyncOnQueue: queue, handler: eventHandler)
}
}
extension EventHub {
final func addSyncListener<T: Event>(owner: AnyClass, syncOnQueue queue: WorkQueue, handler: @escaping (T) -> Void) {
let syncListener: Listener = (owner: owner, handler: { event in
guard let tEvent: T = event as? T else { fatalError("can not cast event to required type") }
queue.syncExec { handler(tEvent) }
})
addToList(eventType: T.eventType, listener: syncListener)
}
final func addAsyncListener<T: Event>(owner: AnyClass, asyncOnQueue queue: WorkQueue, handler: @escaping (T) -> Void) {
let asyncListener: Listener = (owner: owner, handler: { event in
guard let tEvent: T = event as? T else { fatalError("can not cast event to required type") }
queue.asyncExec { handler(tEvent) }
})
addToList(eventType: T.eventType, listener: asyncListener)
}
}
*/

View File

@ -0,0 +1,76 @@
//
// EventHandling.swift
// FirebladeECS
//
// Created by Christian Treffs on 08.10.17.
//
// MARK: - event
public protocol Event: UniqueEventIdentifiable { }
public extension Event {
static var uet: UET { return UET(Self.self) }
var uet: UET { return Self.uet }
}
// MARK: - event handler
public struct EventHandlerRef {
unowned var eventHandlerClassRefUnowned: EventHandler
let eventHandler: (Event) -> Void
}
public protocol EventHandler: class {
func subscribe<E: Event>(event eventHandler: @escaping (E) -> Void)
func unsubscribe<E: Event>(event eventHandler: @escaping (E) -> Void)
weak var delegate: EventHub? { get set }
}
public extension EventHandler {
fileprivate func unowned(_ closure: @escaping (EventHandler) -> Void) {
#if DEBUG
let preActionCount: Int = retainCount(self)
#endif
let unownedClosure = { [unowned self] in
closure(self)
}
unownedClosure()
#if DEBUG
let postActionCount: Int = retainCount(self)
assert(postActionCount == preActionCount, "retain count missmatch [\(preActionCount)] -> [\(postActionCount)]")
#endif
}
/// Subscribe with an event handler closure to receive events of type T
///
/// - Parameter eventHandler: event handler closure
public func subscribe<E: Event>(event eventHandler: @escaping (E) -> Void) {
unowned {
self.delegate?.subscribe(classRef: $0, eventHandler: eventHandler)
}
}
/// Unsubscribe from an event handler closure to stop receiving events of type T
///
/// - Parameter eventHandler: event handler closure
public func unsubscribe<E: Event>(event eventHandler: @escaping (E) -> Void) {
unowned {
self.delegate?.unsubscribe(classRef: $0, eventHandler: eventHandler)
}
}
}
public extension ContiguousArray where Element == EventHandlerRef {
public func index(is eventHandler: EventHandler) -> Int? { // FIXME: this my be costly
return index { (eventHandlerRef: EventHandlerRef) -> Bool in
return eventHandlerRef.eventHandlerClassRefUnowned === eventHandler
}
}
}
// MARK: - event dispatcher
public protocol EventDispatcher: class {
func dispatch<E: Event>(_ event: E)
}

View File

@ -0,0 +1,80 @@
//
// EventHub.swift
// FirebladeECS
//
// Created by Christian Treffs on 09.10.17.
//
public protocol EventHub: class {
func subscribe<E: Event>(classRef eventHandlerRefUnowned: EventHandler, eventHandler: @escaping (E) -> Void)
func unsubscribe<E: Event>(classRef eventHandlerRefUnowned: EventHandler, eventHandler: @escaping (E) -> Void)
weak var sniffer: EventSniffer? { get set }
}
public class DefaultEventHub: EventHub, EventDispatcher {
public var sniffer: EventSniffer?
public init() { }
private var listeners: [UET: ContiguousArray<EventHandlerRef>] = [:]
private func typeEvent<E: Event>(opaqueEvent: Event, eventHandler: @escaping (E) -> Void ) {
guard let typedEvent: E = opaqueEvent as? E else {
fatalError() // TODO: meaningful message
}
eventHandler(typedEvent)
}
private func push(listener newListener: EventHandlerRef, `for` uet: UET) {
if listeners[uet] == nil {
listeners[uet] = []
listeners.reserveCapacity(1)
}
listeners[uet]?.append(newListener)
}
}
// MARK: - event center
extension DefaultEventHub {
final public func subscribe<E: Event>(classRef unownedListenerRef: EventHandler, eventHandler handler: @escaping (E) -> Void) {
let eventListener: EventHandlerRef = EventHandlerRef(eventHandlerClassRefUnowned: unownedListenerRef,
eventHandler: { self.typeEvent(opaqueEvent: $0, eventHandler: handler) })
push(listener: eventListener, for: E.uet)
sniffer?.subscriber(subsribed: E.uet)
}
final public func unsubscribe<E: Event>(classRef listenerRef: EventHandler, eventHandler handler: @escaping (E) -> Void) {
let uet: UET = E.uet
if let removeIdx: Int = listeners[uet]?.index(is: listenerRef) {
let removed = listeners[uet]?.remove(at: removeIdx)
assert(removed != nil)
sniffer?.subscriber(unsubsribed: uet)
}
}
}
// MARK: - event dispatcher delegate
extension DefaultEventHub {
final public func dispatch<E: Event>(_ event: E) {
let uet: UET = E.uet
listeners[uet]?.forEach {
$0.eventHandler(event)
}
sniffer?.dispatched(event: event)
}
}
// MARK: - event dumper
public protocol EventSniffer: class {
func subscriber(subsribed to: UET)
func subscriber(unsubsribed from: UET)
func dispatched<E: Event>(event: E)
}

View File

@ -5,26 +5,26 @@
// Created by Christian Treffs on 08.10.17. // Created by Christian Treffs on 08.10.17.
// //
struct EntityCreated: ECSEvent { public struct EntityCreated: Event {
let entity: Entity let entity: Entity
} }
struct EntityDestroyed: ECSEvent { public struct EntityDestroyed: Event {
let entity: Entity let entity: Entity
} }
struct ComponentAdded: ECSEvent { public struct ComponentAdded: Event {
let component: Component let component: Component
let to: Entity let to: Entity
} }
struct ComponentUpdated: ECSEvent { public struct ComponentUpdated: Event {
let component: Component let component: Component
let previous: Component let previous: Component
let at: Entity let at: Entity
} }
struct ComponentRemoved: ECSEvent { public struct ComponentRemoved: Event {
let component: Component let component: Component
let from: Entity let from: Entity
} }

View File

@ -9,15 +9,15 @@
/// Unique Event Type /// Unique Event Type
public struct UET { public struct UET {
let objectIdentifier: ObjectIdentifier let objectIdentifier: ObjectIdentifier
let type: ECSEvent.Type let type: Event.Type
init(_ eventType: ECSEvent.Type) { init(_ eventType: Event.Type) {
objectIdentifier = ObjectIdentifier(eventType) objectIdentifier = ObjectIdentifier(eventType)
type = eventType type = eventType
} }
init(_ event: ECSEvent) { init(_ event: Event) {
let eventType: ECSEvent.Type = event.uet.type let eventType: Event.Type = event.uet.type
self.init(eventType) self.init(eventType)
} }
} }

View File

@ -0,0 +1,22 @@
//
// Utils.swift
// FirebladeECS
//
// Created by Christian Treffs on 09.10.17.
//
#if os(macOS) || os(iOS) || os(tvOS)
import CoreFoundation
#endif
#if os(macOS) || os(iOS) || os(tvOS)
func retainCount<T: AnyObject>(_ ref: T?) -> Int {
let retainCount: CFIndex = CFGetRetainCount(ref)
return retainCount
}
#else
func retainCount<T: AnyObject>(_ ref: T?) -> Int { return -1 }
#endif

View File

@ -0,0 +1,42 @@
//
// Base.swift
// FirebladeECSTests
//
// Created by Christian Treffs on 09.10.17.
//
import FirebladeECS
struct EmptyComponent: Component { }
class DebugEventHandler: EventHandler {
let eventHub = DefaultEventHub()
var delegate: EventHub?
init() {
delegate = eventHub
subscribe(event: handleEntityCreated)
subscribe(event: handleEntityDestroyed)
subscribe(event: handleComponentAdded)
}
deinit {
unsubscribe(event: handleEntityCreated)
unsubscribe(event: handleComponentAdded)
unsubscribe(event: handleEntityDestroyed)
}
func handleEntityCreated(ec: EntityCreated) {
print(ec)
}
func handleEntityDestroyed(ed: EntityDestroyed) {
print(ed)
}
func handleComponentAdded(ca: ComponentAdded) {
print(ca)
}
}

View File

@ -1,10 +0,0 @@
//
// Components.swift
// FirebladeECSTests
//
// Created by Christian Treffs on 09.10.17.
//
import FirebladeECS
struct EmptyComponent: Component { }

View File

@ -0,0 +1,58 @@
//
// EntityHubTests.swift
// FirebladeECS
//
// Created by Christian Treffs on 09.10.17.
//
import XCTest
@testable import FirebladeECS
class EntityHubTests: XCTestCase {
let entityHub = EntityHub()
override func setUp() {
super.setUp()
entityHub.eventCenter.sniffer = self
}
func testCreateEntity() {
let newEntity: Entity = entityHub.createEntity()
XCTAssert(newEntity.hasComponents == false)
XCTAssert(entityHub.entites[newEntity.uei] == newEntity)
XCTAssert(entityHub.entites[newEntity.uei] === newEntity)
}
func testCreateEntityAndAddComponent() {
let newEntity: Entity = entityHub.createEntity()
let emptyComp = EmptyComponent()
newEntity.add(component: emptyComp)
XCTAssert(newEntity.hasComponents)
XCTAssert(newEntity.numComponents == 1)
XCTAssert(entityHub.entites[newEntity.uei] == newEntity)
XCTAssert(entityHub.entites[newEntity.uei] === newEntity)
}
}
extension EntityHubTests: EventSniffer {
public func subscriber(subsribed to: UET) {
}
public func subscriber(unsubsribed from: UET) {
}
public func dispatched<E>(event: E) where E : Event {
}
}

View File

@ -1,44 +0,0 @@
import XCTest
@testable import FirebladeECS
class FirebladeECSTests: XCTestCase {
class MyEventHandler: EventHandler {
init() {
subscribe(event: handleEntityCreated)
subscribe(event: handleEntityDestroyed)
subscribe(event: handleComponentAdded)
}
deinit {
unsubscribe(event: handleEntityCreated)
unsubscribe(event: handleComponentAdded)
unsubscribe(event: handleEntityDestroyed)
}
func handleEntityCreated(ec: EntityCreated) {
Log.warn(ec)
}
func handleEntityDestroyed(ed: EntityDestroyed) {
Log.warn(ed)
}
func handleComponentAdded(ca: ComponentAdded) {
Log.debug(ca)
}
}
let eventHandler: MyEventHandler = MyEventHandler()
func testCreateEntity() {
let newEntity = Entity()
XCTAssert(newEntity.hasComponents == false)
XCTAssert(newEntity.uei == 1)
XCTAssert(newEntity.numComponents == 0)
let pC: EmptyComponent? = newEntity.peekComponent()
XCTAssert(pC == nil)
}
}

View File

@ -0,0 +1,41 @@
//
// MemoryTests.swift
// FirebladeECS
//
// Created by Christian Treffs on 09.10.17.
//
import XCTest
@testable import FirebladeECS
class MemoryTests: XCTestCase {
func testCheckRetainCount() {
class MyClass {}
let myClass = MyClass()
let initalCount: Int = FirebladeECS.retainCount(myClass)
XCTAssert(initalCount == 3)
let ownerdSelf: MyClass = myClass
_ = ownerdSelf // creates strong reference
let ownedOnceCount: Int = FirebladeECS.retainCount(myClass)
XCTAssert(ownedOnceCount == initalCount + 1) // 4
unowned let unownedSelf: MyClass = myClass
_ = unownedSelf // creates unowned refrerence
let unownedOnceCount: Int = FirebladeECS.retainCount(myClass)
let unownedCount: Int = FirebladeECS.retainCount(unownedSelf)
XCTAssert(ownedOnceCount == unownedCount)
XCTAssert(ownedOnceCount == unownedOnceCount)
weak var weakSelf: MyClass? = myClass
_ = weakSelf // creates weak refrerence
let weakOnceCount: Int = FirebladeECS.retainCount(myClass)
let weakCount: Int = FirebladeECS.retainCount(weakSelf)
XCTAssert(ownedOnceCount == weakCount)
XCTAssert(ownedOnceCount == weakOnceCount)
}
}

View File

@ -0,0 +1,107 @@
//
// PerformanceTests.swift
// FirebladeECS
//
// Created by Christian Treffs on 09.10.17.
//
import XCTest
@testable import FirebladeECS
class PerformanceTests: XCTestCase {
var eventHub: DefaultEventHub = DefaultEventHub()
var entityArray: [Entity] = [Entity]()
var entityContArray: ContiguousArray<Entity> = ContiguousArray<Entity>()
var entitySet: Set<Entity> = Set<Entity>()
var entityMap: [UEI: Entity] = [UEI: Entity]()
static let maxNum: Int = 65536
override func setUp() {
super.setUp()
entitySet.removeAll()
entitySet.reserveCapacity(0)
entityMap.removeAll()
entityMap.reserveCapacity(0)
entityArray.removeAll()
entityArray.reserveCapacity(0)
entityContArray.removeAll()
entityContArray.reserveCapacity(0)
}
func testEntitySetLinearInsert() {
measure {
for i in 0..<65536 {
let newEntity = Entity(uei: UEI(i), dispatcher: eventHub)
entitySet.insert(newEntity)
}
}
}
func testEntityMapLinearInsert() {
entityMap.removeAll()
entityMap.reserveCapacity(0)
measure {
for i in 0..<65536 {
let newEntity = Entity(uei: UEI(i), dispatcher: eventHub)
entityMap[newEntity.uei] = newEntity
}
}
}
func testEntityMapUpdateLinarInsert() {
entityMap.removeAll()
entityMap.reserveCapacity(0)
measure {
for i in 0..<65536 {
let newEntity = Entity(uei: UEI(i), dispatcher: eventHub)
entityMap.updateValue(newEntity, forKey: newEntity.uei)
}
}
}
func testEntityContArrayLinearInsert() {
measure {
for i in 0..<65536 {
let newEntity = Entity(uei: UEI(i), dispatcher: eventHub)
entityContArray.append(newEntity)
}
}
}
func testEntityContArrayFixPosInsert() {
let count: Int = Int(65536)
var entityContArray2 = ContiguousArray<Entity!>(repeating: nil, count: count)
entityContArray2.reserveCapacity(count)
measure {
for i: Int in 0..<count-1 {
let uei = UEI(i)
let newEntity = Entity(uei: uei, dispatcher: eventHub)
entityContArray2[i] = newEntity
}
}
}
func testEntityArrayLinearInsert() {
measure {
for i in 0..<65536 {
let newEntity = Entity(uei: UEI(i), dispatcher: eventHub)
entityArray.append(newEntity)
}
}
}
}