rj00a / evenio

An event-driven Entity Component System
MIT License
137 stars 14 forks source link

Expose the event bump allocator. #44

Open rj00a opened 6 months ago

rj00a commented 6 months ago

For reasons of efficiency, events in evenio are allocated in a bumpalo bump allocator. This allocator is cleared once the top level World::send call returns. It would be useful if users had access to this arena for their own purposes. It should be possible for events to safely contain data borrowed from the allocator, which would eliminate the need for heap allocations in many cases.

Essentially, we remove the 'static requirement from Sender::send and replace it with, say, 'e representing the lifetime of data allocated from the arena. I would expect the 'e lifetime to carry through received events as well, so that data from a received event can be stuffed into a sent event without cloning.

There's also the issue of collections. Custom allocators are still nightly-only, so we would have to fork the standard collections as bumpalo does. I would expect this to be available behind a non-default feature flag.

If #43 happens then I'm guessing we would need a 'w: 'e bound somewhere.

Requirements

andrewgazelka commented 6 months ago

This would be amazing, especially for what I am doing with https://github.com/andrewgazelka/hyperion. Just ran into this issue recently.

andrewgazelka commented 6 months ago

Can you lay out more specifics for how you think this will be done? For instance, will there be a new handler parameter that is specifically used to obtain the bump allocator? Such as a struct named Bump, GlobalBump, or WorldBump? Or do you think we will allow World to be a handler parameter, as is the case in Bevy, I believe?

rj00a commented 6 months ago

I'm not sure exactly. Sender already has an exclusive reference to the allocator in order to queue events, so it would probably make sense to have the allocation API there. If we want received events and sent events to share a lifetime, we might also need some sort of combined SenderReceiver handler param. Because as of now, fn<'a>(Receiver<'a, E>, Sender<'a, ()>) isn't a valid handler and I'm not sure what type-level wizardry is required to make that work.

andrewgazelka commented 5 months ago

I'm not sure exactly. Sender already has an exclusive reference to the allocator in order to queue events, so it would probably make sense to have the allocation API there. If we want received events and sent events to share a lifetime, we might also need some sort of combined SenderReceiver handler param. Because as of now, fn<'a>(Receiver<'a, E>, Sender<'a, ()>) isn't a valid handler and I'm not sure what type-level wizardry is required to make that work.

CleanShot 2024-05-15 at 11 04 56@2x

Are you sure Sender needs an exclusive reference to bumpalo? I'm pretty sure allocating just requires a shared reference it's not Send or Sync.

So, since everything is not Send and Sync right now, you should be able to have a shared reference, I think.

rj00a commented 5 months ago

Yeah since Sender is !Send and !Sync I think we can just make everything internally mutable.