In programming languages the support for concurrency is called the Concurrency Model. I have experience with the Java concurrency model, but recently I read about another language with a revolutionary memory model. This language is Erlang.
Erlang is a concurrent, garbage-collected functional language and runtime system. It was designed by Ericsson in 1986 and was released as open source in 1998. Now it is gaining more and more ground in Internet related software industry and I’m not surprised.
At the base of the Java Concurrency Model are synchronized shared data structures (Shared-memory model), in this case, synchronization trough locks is required to protect the shared objects from concurrent modiﬁcations.
Instead of a shared data structures approach, Erlang uses techniques based on message passing (Exchange-message model). Efﬁcient concurrency through message passing requires a particular memory architecture. Following I’ll quickly introduce different approaches.
Private Heaps Architecture
Till the 2001, the Ericsson Erlang/OTP R8 implementation had exclusively a memory architecture where each process allocates and manages its own memory area. In this solution, each process allocates and manages its own private memory area whit: PCB, private stack and private heap. In this architecture, message passing is performed by copying the message from the heap of the sender to the heap of the receiver, and then inserting a pointer to the message in a queue data structure (called mailbox) of the receiver.
Pro: Easy and efficient garbage collection methods. Improved cache locality.
Cons: Message passing expensive. More space needs.
Shared Heap Architecture
In the private heap architecture, sending a message to another process involves copying the message data to the receiver’s heap. This is an O(n) operation, where n is the size of the message. This problem can be avoided with a shared heap. Each process can still have its own stack, but there is also a global heap shared by all processes. This architecture simplifies the process communication, in fact in order to send a message, a sender can just copy a reference of the message (which is allocated in the shared heap) in the receiver’s mailbox. In this way massage passing is a constant time operation.
Pro: Fast message passing. Less space needs.
Cons: Larger root set for the garbage collector and higher garbage collection time.
As we have seen each of the memory architectures described has its advantages. The private heap system allows a fast and cheap reclamation of the memory. Meanwhile, the shared heap system optimizes the interprocess communication. The hybrid solution tried (and failed!) to combine these advantages. In this solution, every processes has its own heap used for local data. In addition a global shared heap is present, and it’s in this heap that messages are placed. In order to make the garbage collection efficient, this architecture forbids any pointers from the shared heap to any of the private heaps.
Pro: Fast message passing. Less space needs. Efficient local garbage collector.
Cons: Still large root set for the shared garbage collection area. Necessity to know at compile time if a data is local or will be sent as a message.
The first two architectures: private heaps and shared heap, have been implemented and released as part of Erlang/OTP R8 and the user can choose between them through a configuration option. The third architecture, hybrid architecture, unfortunately, due to excessive locking and issues with garbage collecting was prohibitively slow and hard to maintain, so it was dropped.