What does, to what level of granularity, the actor belong to in Elixir and Erlang? Process? Thread? Any other unit?
Does it always remain on the same level, or can there be actors that belong to process and those that belong to threads?
In the specification of actor model it says the anything that’s an actor can create their own actors, namely, actors that operate on a lower level of granularity.
The “actor” is the “(green) thread” is the “process” (but important: not an OS process). It belongs to the VM. It’s not a true actor in the Carl Hewitt sense, don’t try to approach it from a theoretical perspective, and don’t follow Hewitt’s spec. The Erlang folks built it and then later realized that it “looks kinda like a Hewitt actor without having to squint your eyes”. But Hewitt came up with the actor as a way to explore different computational paradigms; Erlang processes have, from the beginning existed to explore different failure domain paradigms. They just happen to look alike by accident.
As a matter of terminology, they are not officially called actors. They are also not called threads, as typically threads imply shared memory. OS processes imply no-shared-memory, which is (I think) why they are officially called processes in the BEAM VM. However they get scheduled in an M:N fashion, often thousands or hundreds of thousands, across a (usually fewer) number of OS processes; by default the modern BEAM VM spins up as many OS processes as you have cores available, unless you have some cgroup parameters set up or override with a flag.
Not by default in the VM. Almost all processes are truly, in a “flat” space. However, the standard library (OTP) gives you robust, battle-proven tools to build supervision trees, which lets processes “manage” other processes. This is such a useful pattern that in a “best-practices” OTP application, all your processes will be somewhere in the tree, and many of the monitoring and observability tools will assume that all of your process are somewhere in the tree. And most people think of their OTP application in terms of the supervision tree.
Typically the manager processes are extremely lightweight and “have one job” which is managing, and do nothing else, so up to a few configuration details, almost all of these supervisors look the same, it is only the leaf nodes that “do things”
Starting from the bottom up. The Erlang VM, the BEAM, is one OPS process which runs a number of threads, typically one per core. In many ways it is like an OS in that implements itself most of the typical OS things like processes, memory management, standard libraries, etc itself. So Erlang/Elixir processes are implemented in the BEAM itself and do not use OS processes or threads. This is how the BEAM can run literally millions of Erlang processes on one node (the maximum is somewhere around 150 million) as doing this using OS processes/threads would be impossible. To make it even more fun you can of course run multiple BEAMs on one machine as they are just OS processes.
The BEAM uses OS threads internally to do load balancing over all the cores. Each thread runs what is called a scheduler which manages processes, context switching, memory management, etc for that thread. All these schedulers are of course cooperating with each other and keep track of load to do load balancing internally almost automagically as it is something you seldom need to be aware of. It is just there.
It is a truly fantastic VM in all respects.
In many ways an Erlang process is very OS process like but much much much lighter. It is these process which can be viewed as actors as in many ways they behave in a very actor-like way, not in everything but in many things. Now Erlang/BEAM and hence Elixir were developed in a very pragmatic way: there was a problem we needed to solve and that was much more important than which theoretical model the solution was based on. It became functional and actor like because that worked!
I was talking with Carl Hewitt about this and he saw this as a strength of the actor model. You got there from both a theoretical POV and a pragmatic POV.
There are only just processes (actors) under BEAM. Threads are what VM is using to run your code but you don’t have to think about them. So as programmer you only have BEAM processes that you use.
an interesting analogy, I think: if you’ve ever used ZFS, the reason why it’s so powerful is that it does a lot of filesystem management things at a layer higher than standard filesystems would do, and it kind of doesn’t trust the hardware to do the right thing; because it knows what it needs based on a combination of what you’ve told it and what it’s seen. The BEAM is kind of the same way, it’s powerful because it does process management things at a layer higher than most programs would it. And it kind of doesn’t trust the OS to do the right thing; because it knows what it needs based on a combination of what you’ve told it and what it’s seen. /endshowerthought