jonascarpay / apecs

a fast, extensible, type driven Haskell ECS framework for games
392 stars 43 forks source link

WIP remove MonadIO requirement #80

Open DavidEichmann opened 3 years ago

DavidEichmann commented 3 years ago

This is intended to allow both pure and impure stores (and hence underlying monad) to be used under the hood. I think most stores can be made pure with little performance hit as updating the world record will be fast compared to updating the store itself (e.g. updating an IntMap). This should allow the whole world to be expressed as an immutable data type.

DavidEichmann commented 3 years ago

@jonascarpay This is just a start! But maybe you can have a look at the changes to Core.hs and Stores.hs to see if I'm on the right track.

jonascarpay commented 3 years ago

The crux of the issue for me is this:

I think most stores can be made pure with little performance hit as updating the world record will be fast compared to updating the store itself

If this is true, this would be a clear win. I'm not sure whether or not it is true though; for IntMaps the overhead is small, but for a mutable cache it might be a lot bigger. I don't know if GHC manages to optimize a State that doesn't change to the same performance as a Reader. How far from actually compiling is this (also why is there no CI :S)? I'd love to see some performance numbers.

Somwhat related; one thing I'm experimenting with is rewriting e.g. Get to

class Get m c where
  get :: Entity -> m c

which would allow the same thing since m could be State World or ReaderT MutableWorld IO. Unfortunately being this general requires a lot of trickery, so I'm not sure this will ever work.

DavidEichmann commented 3 years ago

I've almost got this building now. I just need to get TH to create the world init function to be in m not IO. I have left the Cache store in IO due to it's performance characteristics.

DavidEichmann commented 3 years ago

I think I've introduced some bugs :-( e.g. cmap needs to be updated. Initial runs of the benchmarks shows faster initialization (dono why) and slower updates (also not sure why).

jonascarpay commented 3 years ago

Initial runs of the benchmarks shows faster initialization (dono why) and slower updates (also not sure why).

I'm seeing similar results here https://github.com/jonascarpay/apecs/issues/72#issuecomment-856752022. The way the benchmark numbers work out can be kind of weird. As long as the total time is still lower, I think it's fine. What kind of cmap bugs did you run into, did the tests catch them?