I'm currently implementing a small Entity Component System as a learning project, it's been a good way to learn about generics, memory, and performance.
All my components derive from a
Component
class. This also stores a unique
unsigned int
as a static variable to identify the component type.
On each entity I store a pointer to the component in a
std::unordered_map
with the unique integer as the key for the entity it is attached to.
However this is very slow in comparison to other systems. To instantiate 4000 entities, and add 3 new components to each takes ~2.1ms, however using the EnTT library it only takes ~0.6ms.
Instantiating 4000 entities and 12000 components only takes 0.16ms due to a custom allocator. The rest of the time is taken up by this function:
1 2 3 4 5 6 7 8 9 10 11
|
class Entity
{
// ...
private:
std::unordered_map<unsigned int, Component*> mComponentMap;
};
void Entity::AddComponent(unsigned int id, Component* component)
{
mComponents.emplace(id, component);
}
|
The process roughly looks like this:
1 2 3 4 5 6 7
|
for(int i = 0; i < 4000; i++)
{
Entity* entity = ecs.CreateEntity();
entity->AddComponent(Transform::ID, ecs.CreateComponent<Transform>());
entity->AddComponent(Model::ID, ecs.CreateComponent<Model>());
entity->AddComponent(Input::ID, scene.CreateComponent<Input>());
}
|
Where
Transform
,
Model
, and
Input
subclass a base
Component
class (just using them as examples).
ecs.CreateEntity()
and
ecs.CreateComponent<Component>()
instantiate and return new instances using the custom allocator.
Does anyone have any suggestions on alternatives for adding this data in a more efficient way in the
Entity::AddComponent
function?, be it some custom structure or something else? Systems like this are normally used for real time applications such as games, so the performance is normally fairly critical.
Let me know if I need to elaborate further :)
Thanks!