ayebear / es

An easy to use, high performance, C++14 "Entity Component System" library.
MIT License
12 stars 2 forks source link

Question on cache friendliness #11

Closed nodev closed 8 years ago

nodev commented 8 years ago

Hi,

Sorry to bother you once again but I wanted to know how component storage is cache friendly. Of course you use std::vector to store components but es::Component (and hence, derived components) isn't std::is_standard_layout or std::is_pod so the data is not contiguous in the memory. Well, that's my understanding of C++ at least.

ayebear commented 8 years ago

Not all components are POD. What if you want to store some larger components that use std::vector/std::unordered_map/sf::Sprite? Those types of variables are going to be allocated on the heap anyway, outside of the component itself. Either way, without any of those properties, most of your components should fit inside cache (excluding heap-allocated objects within those components). C++ structs can also have padding, which might make it not considered POD, but it certainly wouldn't affect storing in cache other than taking up more space.

Honestly, this is a much smaller issue than the real problem of iterating through entities with multiple components. Lets say you have a simple movement system, that just handles Position and Velocity. The entity query function might decide that iterating through velocity components is more efficient, since there are less instances of these than positions (could have some non-moving entities). So, it iterates through the Velocity components in order, being very cache efficient. But, since the loop requires accessing/changing the Position components, it will need to load those into cache as well. Both the Velocity and Position components might not fit into cache, so they could each push each other out, making everything less cache efficient. This is especially the case for when the Position components are not being processed in order, so a chunk of the vector of position components will probably be loaded into cache for each velocity component.

By improving the order in which components are stored, this may have a bigger performance improvement than worrying about micro-optimizing for pod/standard layout components. But there would have to be benchmarks done before doing any performance improvements.

ayebear commented 8 years ago

http://en.cppreference.com/w/cpp/types/is_pod http://en.cppreference.com/w/cpp/types/is_standard_layout

These are false for structs with private variables. They should still be contiguous though, but you'd have to really test to make sure. I also wonder how inheritance affects struct layout in memory.

nodev commented 8 years ago

I think that's where my interpretation of entity component system differs from yours. I think if you're storing something like sf::Sprite as your component, you're doing it wrong. You should only have a handle or plain data to a component and system should have the logic on operating on it or you directly do it. This has some problems of its own though.

Secondly, I agree about the ordering optimization but again I think iterating through component of same type in a system is more important than iterating through entities.

But yeah, this is premature optimization stuff and would need testing if it is even a problem. I was mainly concerned that component data stored inside memory maybe fragmanted due to not being POD.