I think it’s a really cool post! Elixir is clearly going in a very different direction to Gleam when it comes to types and I look forward to trying it. I can’t speculate what it’ll be like in the mean time, but I am excited for it.
1 Like
What you want to know is not whether they are crash-proof, but whether they are fault-tolerant. Let me try to provide some good points as opposed to being a fan of either side.
- Crash-proof: Tokio isolates panic unwinding within each task; the Erlang VM isolates exception throwing within each process. Neither of them should “crash” unless, e.g. you do
panic = abort
, or use a NIF that SegFaults, respectively. However, the Erlang VM has a tiny error kernel, so its implementation is more reliable in theory. - State corruption: Tokio tasks share memory through synchronization primitives, so state corruption is more likely to mediate from one task to another. Erlang processes do not share memory, and instead pass message around by copying them, so states of Erlang processes are highly isolated. Axum encourages shared state through
Clone + Send + Sync + 'static
struct
s (e.g.,Arc<Mutex<_>>
) by feeding them as magic arguments to request handlers, which can be a large source of state corruption; Erlang only allows the actor model, and encourages processes to not expect other processes to reply. Note that unwind should only cause low-level memory corruption if it is notUnwindSafe
. - Scheduling: Tokio tasks are cooperatively scheduled, so you should call
yield_now
for long-running functions and run blocking code (e.g.syscall
) on a blocking thread, or else you can suffer from stalls; Erlang processes are preemptively scheduled, so you can do stupid things and get away with it. - Debugging: When you do have faults, Erlang provides a superior interactive debugging experience. The Tokio debugger is highly experimental and people just read the logs or traces instead.
- Mindset: Rust is perfect for problems you understand as a whole, and problematic for situations with many unknown unknowns; Erlang takes the burden off of developers shoulders by applying the end-to-end argument on fault-tolerance. This is why I tend to reach for Axum when I need to serve just a few well-defined requests, a small problem, but reach for Phoenix whenever I feel the problem is larger or I do not fully understand it.
Hope this helps!
Steven Hé (Sīchàng)
12 Likes
It would be an interesting experiment to see if you could map types between Elixir and Gleam.
The two systems are rather different so you wouldn’t be able to do huge amounts in practice. You would be able to generate Elixir bindings to Gleam generated code though!