Changed array types, increasing performance

This commit is contained in:
Brychan Dempsey 2021-06-11 20:55:05 +12:00
parent 529f99abbd
commit 999ffa41dd
3 changed files with 36 additions and 17 deletions

View File

@ -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<Object> componentArray = new ArrayList<>();
private List<Object> componentArray;
// The mappings between data and entity
private Map<Entity, Integer> entityComponentDataMap = new HashMap<>();
private Map<Integer, Entity> componentDataEntityMap = new HashMap<>();
private Map<Entity, Integer> entityComponentDataMap;
private Map<Integer, Entity> 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

View File

@ -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;

View File

@ -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<Entity> 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<Entity> unusedEntities;
private List<BitSet> 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<Entity> outOfBounds = new ArrayList<>();
Deque<Entity> 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