4 ms·
Ractor is cool, but I've been wondering why it uses the async `async_trait` rather than native async traits. Is it just because it came out before async traits
by simonask 2y ago
Ractor is cool, but I've been wondering why it uses the async `async_trait` rather than native async traits. Is it just because it came out before async traits were stabilized, and now code relies on it and it would be a breaking change to migrate?
For context, the `async_trait` crate makes futures from trait methods that are wrapped in `Pin<Box<dyn Future<...>>>`, which means that every async call to a trait method must make a heap allocation. This is currently a necessary thing to do if async trait methods were invoked with dynamic dispatch (through `dyn Actor`), but the `Actor` trait has associated methods, so that is already not generally possible.
I realize that methods on the `Actor` trait return futures that are `Send`, but specifically for an actor framework that feels like a very specific design choice that isn't universally good or necessary. Another design would give let the spawned task that executes the actor's messages exclusive access to the actor (so `handle()` could take `&mut self`).
I've ended up implementing a simple alternative design in my own project (it's not fundamentally very hard, but doesn't have all the features, like supervision) because the per-message heap allocations and internal locking became wasteful for my use case.
- SkiFire13 2y ago> I've been wondering why it uses the async `async_trait` rather than native async traits From their crate documentation[0]: > The minimum supported Rust version (MSRV) is 1.64. However if you disable the `async-trait` feature, then you need Rust >= 1.75 due to the native use of `async fn` in traits. [0]: https://docs.rs/ractor/0.13.0/ractor/index.html https://docs.rs/ractor/0.13.0/ractor/index.html