I'm not fully able to follow what the article is trying to say.
I got especially confused at the actor part, aren't actors share nothing by design?
It does to say there's only 1 actor, so I guess it has nothing to do with actors? They're talking about GenServer-like behavior within a single actor.
As I write this, I'm figuring out maybe they mean it's like a single actor GenServer sending messages to itself, where each message will update some global state. Even that though, actors don't yield inside callbacks, if you send a message it gets queued to run but won't suspend the currently running callback, so the current method will run to completion and then the next will run.
Erlang actors do single-threaded actors with serialized message processing. If I understand the article, that avoids the issue it brings up completely as you cannot have captured old state that is stale when resuming.
There every complex enough distributed system will eventually implement Erlang but in an ad-hoc and not very good way. Quite a lot of systems ended up with actors. TigerBeetle in Zig, FoundationDB in C++. But they miss critical aspect of it and that’s isolated memory between processors. And they don’t know how to yield unless they do it on IO or do cooperative yielding. The global shared heap is really the dangerous part though. Rust could avoid the danger by asserting some guarantees at compile time.
I can't imagine those examples you picked implemented in Erlang performing anywhere close to the Zig/C++ ones. So the "ad-hoc subset" there is by design.
They have realised that, in single-threaded code, an implicit mutex is created between each call to await, and therefore state variables can usually be organised in such a way to avoid explicit mutexes. Of course, one strongly suspects that such code will involve a lot of boolean variables with names such as “exclude_other_accesses_to_data”.
It’s half-baked actors. Well not baked at all (“no-bake actors”?) as isolated heaps and shared nothing is not easy to accomplish. OS processes can do it but they can be heavyweight. BEAM VM does a great job of it, though.
Share nothing is often too coarse grained serialization for all situations. Using a lock or other shared memory primitive (RCU, hazard pointers, etc) can lead to better performance due to smaller granularity of data protected and latency necessary to access the data. Optimizing for latency is very different from optimizing for throughput.
I got especially confused at the actor part, aren't actors share nothing by design?
It does to say there's only 1 actor, so I guess it has nothing to do with actors? They're talking about GenServer-like behavior within a single actor.
As I write this, I'm figuring out maybe they mean it's like a single actor GenServer sending messages to itself, where each message will update some global state. Even that though, actors don't yield inside callbacks, if you send a message it gets queued to run but won't suspend the currently running callback, so the current method will run to completion and then the next will run.
Erlang actors do single-threaded actors with serialized message processing. If I understand the article, that avoids the issue it brings up completely as you cannot have captured old state that is stale when resuming.