bevy
bevy copied to clipboard
Remove crossbeam-channel as a runtime dependency
Objective
Fixes #7153. crossbeam-channel is a great crate, but it may not be the right fit for a lot of Bevy's use cases. It inherently allocates an inner representation, and uses an Arc-like indirection to access it via the sender and receiver. This might be useful when we want to separate the two and move them to their own tasks on different threads, but this may represent additional overhead when working with the channel. We also tend to only use try_send and try_recv to avoid blocking at all costs. This makes sense given that we (almost) never want to block the current thread and wait on the other side to be populated.
Solution
Remove all runtime dependency on crossbeam-channel, and replace it with the concurrent-queue, which is already in use by bevy_ecs, bevy_tasks, and by a good chunk of the async-* dependencies Bevy is already using. Where absolutely necessary, the queue will be wrapped in an Arc to provide a similar interface as before.
The queue provides access to both ends of the queue from a single interface, does not require internal indirection, pushes and pops are strictly non-blocking, provides a similar internal implementation to that of crossbeam-channel, and allows us to remove one more dependency when compiling Bevy.
One potential improvement is to explicitly wrap the case of unclosable and unbounded queues in an Arc to create an infallible event queue.
Changelog
TODO
Migration Guide
TODO
Performance-wise how do these compare? Are there benchmarks of crossbeam vs concurrent-queue anywhere under different load conditions? Some usages of these (such as the ID lifecycle stuff) might be affected by perf regressions. I'm in favor of removing dependencies, but we're notably taking on new code with the wrappers, and increasing the number of queue variants (ConcurrentQueue, Arc<ConcurrentQueue>, EventQueue, EventReader, EventSender, instead of just Sender/Receiver), making this feel a bit more like a lateral move (I do acknowledge the benefits stated above though). But combine that with the "perf" question and I start to question why we're rocking the boat here.
I don't have time to review this right now, but I think this PR is probably worth doing due to the fact that crossbeam-channel uses user-space spinlocks, which is pretty much always a bad idea in user-space applications