Entity Component System - Map Performance

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!
Last edited on
Would it be practical to replace the map with a vector?
1
2
3
4
5
6
7
8
9
10
11
12
13
class Entity
{
// ...
private:
    std::vector<Component*> mComponentVector;
};

Entity::Entity(): mComponentVector(Component::maxID){}

void Entity::AddComponent(unsigned int id, Component* component)
{
    mComponentVector[id] = component;
}
Yeah I was thinking along the lines of this, my only concern is it's a lot of wasted memory.

Using this I do get a massive performance increase though, down to ~0.6-0.7ms for 4000 entities, 3 components each.

If you have 10000 entities, and 150 different component types. If we say a pointer is 8 bytes then we're using 11.4mb just to store a few components on each entity.

Would you consider that an unreasonable overhead for what it is? I think I will go with this method, but is there some other method that could provide a performance increase without as much wasted memory?
If it's only a few components per entity, why not simply an intrusive linked list of components, and use linear search to get to the right one?
Would you consider that an unreasonable overhead for what it is?
Particularly for a game this doesn't seem too much memory. On the other hand: why would you need that many [unnecessary] entities?

When inserting/erasing is the most time critical process a std::list would be an appropriate container.

Beware of unnecessary optimization. Who cares for unnoticeable performance...
Note that I said an intrusive linked list, since that doesn't require any extra allocations per element. You just put the point to the next node on the base class.
Topic archived. No new replies allowed.