This document discusses different approaches to concurrency including operating system processes and threads, green threads, and lightweight processes as used in Erlang, Elixir, Go, and other languages. OS processes have separate memory but are expensive while threads share memory and can block each other. Green threads are scheduled by a virtual machine instead of the OS but cannot use multiple CPUs. Erlang processes are lightweight, isolated processes managed by the VM rather than the OS which allows for easy scaling and fault tolerance through message passing.
3. os processes
Pros
They have separate sections of memory.
No side effects: If VIM crashes, Chrome is unaffected.
Cons
Unfortunately, expensive...
4. os threads
Pros
Lighter than OS processes
They do not block each other
They run on separate CPUs, so they are truly parallel
Cons
Still pretty heavy weight
Shared memory
5. green threads
Threads that are scheduled by a virtual machine, rather than the
OS.
Pros
They don't take up a lot of memory.
Cons
Green thread implementations normally cannot assign work to
multiple processors.
A blocking I/O operation can block all green threads.
6. so how heavy is "heavy"?
A POSIX thread has a configurable stack size. On my
machine, the default is 8Mb.
JVM, .NET, RubyVM, and CPython all use 1Mb by default.
Therefore, memory usage will add up quickly.
7. [Erlang] is a concurrent language – by that I mean that
threads are part of the programming language, they do not
belong to the operating system. That's really what's wrong with
programming languages like Java and C++. It's threads aren't in
the programming language, threads are something in the
operating system – and they inherit all the problems that they
have in the operating system. One of the problems is granularity
of the memory management system. The memory management
in the operating system protects whole pages of memory, so the
smallest size that a thread can be is the smallest size of a page.
That's actually too big.
-- Joe Armstrong
8. goroutines
Initial stack size is 2kb (as of 1.4), but then is dynamically
allocated
goroutines are green threads that are multiplexed as needed
onto native threads, so there isn't a 1:1 mapping.
11. so...
Not an OS process, but still isolated.
No side effects. If a process crashes, other processes are not
affected.
Managed by the VM, rather than the OS.
Immutable data structures sidestep shared mutable state.
Processes communicate through message passing.
Fault-tolerant
12. go on...
Lightweight memory footprint.
Dynamically allocated stack.
All of this applies to Elixir as well.
{_, bits} = :erlang.process_info(
spawn(fn -> nil end),
:memory
)
bits / 8 # 340.0
13. who cares?
we are now able to easily push our systems to over 2 million tcp
connections!
-- WhatsApp (https://blog.whatsapp.com/196/1-million-is-so-
2011)