diff --git a/javaecs/src/main/java/nz/ac/massey/javaecs/ComponentArray.java b/javaecs/src/main/java/nz/ac/massey/javaecs/ComponentArray.java index f68dae8..15f0e5d 100644 --- a/javaecs/src/main/java/nz/ac/massey/javaecs/ComponentArray.java +++ b/javaecs/src/main/java/nz/ac/massey/javaecs/ComponentArray.java @@ -16,18 +16,22 @@ package nz.ac.massey.javaecs; import java.util.Map; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.ArrayList; class ComponentArray{ // The object data array - private List componentArray = new ArrayList<>(); + private List componentArray; // The mappings between data and entity - private Map entityComponentDataMap = new HashMap<>(); - private Map componentDataEntityMap = new HashMap<>(); + private Map entityComponentDataMap; + private Map componentDataEntityMap; + public ComponentArray(int initialSize){ + componentArray = new ArrayList<>(initialSize); + entityComponentDataMap = new HashMap<>(initialSize); + componentDataEntityMap = new HashMap<>(initialSize); + } /** * Gets the data Object associated with the entity. * @param entity the entity to find data for diff --git a/javaecs/src/main/java/nz/ac/massey/javaecs/ComponentManager.java b/javaecs/src/main/java/nz/ac/massey/javaecs/ComponentManager.java index c501cfa..9aa4db4 100644 --- a/javaecs/src/main/java/nz/ac/massey/javaecs/ComponentManager.java +++ b/javaecs/src/main/java/nz/ac/massey/javaecs/ComponentManager.java @@ -121,11 +121,21 @@ class ComponentManager{ * @return true if the component was registered successfully, else false */ protected boolean registerComponent(Type type){ + return registerComponent(type, 16); + } + + /** + * Registers the component type + * @param type the class type to register + * @param arraySize the number of elements to prereserve space for. + * @return true if the component was registered successfully, else false + */ + protected boolean registerComponent(Type type, int arraySize){ if (componentArrays.containsKey(type)){ Engine.writeErr("Component " + type.getTypeName() + " is already registered"); return false; } - componentArrays.put(type, new ComponentArray()); + componentArrays.put(type, new ComponentArray(arraySize)); indexComponentType.put(componentPosIndex.size(), type); componentPosIndex.put(type, componentPosIndex.size()); return true; diff --git a/javaecs/src/main/java/nz/ac/massey/javaecs/EntityManager.java b/javaecs/src/main/java/nz/ac/massey/javaecs/EntityManager.java index 4923578..2853823 100644 --- a/javaecs/src/main/java/nz/ac/massey/javaecs/EntityManager.java +++ b/javaecs/src/main/java/nz/ac/massey/javaecs/EntityManager.java @@ -9,10 +9,10 @@ package nz.ac.massey.javaecs; */ import java.util.BitSet; -import java.util.LinkedList; +import java.util.Deque; import java.util.List; import java.util.NoSuchElementException; -import java.util.Queue; +import java.util.ArrayDeque; import java.util.ArrayList; // Define the manager classes internally - should be moved to seperate source files as appropriate @@ -22,7 +22,11 @@ import java.util.ArrayList; * I.e. Controls adding and removing entities, and registration and deregistration of components. */ class EntityManager{ - private Queue unusedEntities; + // According to https://stackoverflow.com/questions/12524826/why-should-i-use-deque-over-stack + // ArrayDeque is likely faster than a LinkedList, when used as one. + // We can also supply a size to the constructor of ArrayDeque, which avoids resizing the collection + // at initialisation time (took 1.4s vs 1.8s for 1M) + private Deque unusedEntities; private List entityRegistrations; private int maxSize = 1024; @@ -30,8 +34,8 @@ class EntityManager{ * Initialise the EntityManager with the default max size of 1024 */ public EntityManager(){ - unusedEntities = new LinkedList<>(); - entityRegistrations = new ArrayList<>(); + unusedEntities = new ArrayDeque<>(maxSize); + entityRegistrations = new ArrayList<>(maxSize); // Init to maxSize to increase performance for (int i = 0; i < maxSize; i++) { unusedEntities.add(new Entity(i)); @@ -45,8 +49,8 @@ class EntityManager{ */ public EntityManager(int maxEntities){ maxSize = maxEntities; - unusedEntities = new LinkedList<>(); - entityRegistrations = new ArrayList<>(); + unusedEntities = new ArrayDeque<>(maxSize); + entityRegistrations = new ArrayList<>(maxEntities); for (int i = 0; i < maxEntities; i++) { unusedEntities.add(new Entity(i)); @@ -180,7 +184,7 @@ class EntityManager{ // Consistency should be maintained. // This is computationally expensive; we must re-order every assigned entity above newSize, if the newSize is smaller if (newSize < maxSize){ - List outOfBounds = new ArrayList<>(); + Deque outOfBounds = new ArrayDeque<>(maxSize - newSize); for (int i = newSize; i < maxSize; i++) { Entity entityI = Entity.asEntity(i); if (!unusedEntities.remove(entityI)){ @@ -189,14 +193,15 @@ class EntityManager{ outOfBounds.add(entityI); } } - for (Entity integer : outOfBounds) { + while(outOfBounds.size() > 0){ + Entity old = outOfBounds.remove(); Entity newPos = addEntity(); - setRegistrations(newPos, getRegistrations(integer)); + setRegistrations(newPos, getRegistrations(old)); // Invoke an update in the SystemManager - systemManager.entityDestroyed(integer); + systemManager.entityDestroyed(old); systemManager.entityRegistrationsChanged(newPos, getRegistrations(newPos)); // Invoke the change in the components - componentManager.moveAllComponentData(integer, newPos, getRegistrations(integer)); + componentManager.moveAllComponentData(old, newPos, getRegistrations(old)); } for (int i = newSize; i < maxSize; i++) { // Remove out-of-bounds data