Comment by adamnemecek

5 years ago

I have been thinking about this as well lately. For my app (http://ngrid.io) I'm using a custom built Entity-Component-System (https://en.wikipedia.org/wiki/Entity_component_system) based UI framework in Rust.

In the ECS paradigm, everything is stored as struct-of-arrays as opposed to array-of-structs (https://en.wikipedia.org/wiki/AoS_and_SoA) and as a result, your serialization becomes trivial. You are not chasing pointers to other objects when serializing. Apple's Core Data takes the object graph approach and it's a real clusterfuck.

ECS is very similar to databases in that your data is normalized and things are referenced by offsets rather than pointers https://floooh.github.io/2018/06/17/handles-vs-pointers.html).

Why roll your own thing as opposed to use say SQLite? If you use SQLite, you will probably have some OOP on top of it which introduces a serious impedance mismatch. With ECS, you cut that whole layer out.

I'm guessing that I'm losing on some atomicity but for my use case that doesn't matter that much.

ECS is useful for real-time, but it means that you are rolling your own query logic. This is fine for the runtime of game engines because they generally aren't dealing with that many data types(for the very most complex AAA games, perhaps a few hundred components) and the queries used at runtime are simple and tend to demand optimization at the data structure level.

If your purpose is an editing tool you may want to reconsider. Editing changes the goal in a very substantial way and the complexity of your queries goes way up, which is where SQL syntax absolutely shines.

  • FWIW, a game I'm writing uses in-memory SQLite as its ECS, mostly because I wanted to see if I could. SQLite is surprisingly performant. My game is not realtime, but I tested it, and I could actually redraw the screen at 60+ FPS while querying for render data every frame, and I still had lots of frame time to spare.