Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Contiguous memory storage for your ECS buffers. #46

Open
forbiddencactus opened this issue Jan 25, 2022 · 1 comment
Open

Contiguous memory storage for your ECS buffers. #46

forbiddencactus opened this issue Jan 25, 2022 · 1 comment
Labels
enhancement New feature or request

Comments

@forbiddencactus
Copy link

Hello! I stumbled upon this project while looking for something completely different and I immediately took interest since I've been writing a Swift hobby game engine and so Fireblade is really interesting to me! I have a suggestion based on my own learnings about Swift to make this ECS system much faster, and I figured I'd drop it here in case it's useful!

Something I learnt from writing my own Swift engine with a data oriented design is that at the moment it's impossible to (easily) contiguously allocate instances of classes in memory... Swift's memory model just doesn't allow for it. In your Component protocol, you enforce an 'AnyObject' inheritance, which means that your components will be reference types and allocated by the swift runtime (which ultimately calls malloc), and the pointers to these objects will be allocated to wherever malloc thinks is appropriate, in a non ecs/cache friendly way. ContiguousArray unfortunately won't fix this problem since it'll just allocate a contiguous array of references to your class instances. ContiguousArray isn't truly 'contiguous' for reference types, as far as I've investigated.

This means that whenever one of your systems is iterating over a group of entity/components, it will likely incur a large amount of cache misses as you access/process the data in every component, and won't be very performant.

I actually stumbled into this problem myself, and even went as far as trying to hack into the Swift runtime in order to solve this issue (and it is somewhat ultimately solveable, with very involved hacking), but ultimately it felt like I was working against the language design, and so I just decided to use value types for my components, so that any contiguous buffers are actually contiguous and cache friendly.

My suggestion is to go with value types for your ECS system, which should solve the problem neatly.

Great job on Fireblade! I really hope to see this develop. :)

@forbiddencactus forbiddencactus added the enhancement New feature or request label Jan 25, 2022
@ctreffs
Copy link
Member

ctreffs commented Jan 27, 2022

Hi @forbiddencactus,

thanks for your feedback :-)

Yes you are very right - currently Components are not cache friendly since they are reference types.
This is a limitation for now, I'm aware.
And you are also right about the value types being the right fit here 👍
RealityKit has a Swift based ECS implementation that uses value types and it's the right approach.
Ultimately I'd like to have an Allocator that is managing memory entirely and can be optimized according to the specific needs of the Nexus.

I'd love to refactor FirebladeECS to using value types, but since I'm a hobbyist myself it's a huge undertaking besides the regular job.
Maybe you're interested in helping with it?
Would love to have you on board.
Let me know :-)

@stackotter stackotter mentioned this issue Mar 26, 2022
14 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants