I read Joe Armstrong's 'Programming Erlang', and the 'n times faster in n core machine' theory. The efficient way to multicore programming in Erlang is to use lots of processes (threads).
I'm a C++ programmer, so I am curious about the difference between making lots of threads in C++ and making lots of processes in Erlang. I understand dealing with threads in C/C++ is not that easy. Also I know locking/unlocking makes the system slow down. But it is not impossible, right?
So.. why is Erlang a muticore friendly language? Is it just because it's easy to program?
I'm making an online game server for a MMORPG, that's why I'm interested in Erlang as an alternative server language.
(I already read this question but I think it's not the question I'm looking for.)
No, it's not impossible, but Erlang does make it much easier. The key is not sharing state among the processes. Erlang achieves this by virtue of it being a functional language. The function should have no side effects nor should it access any variable state (other than the arguments passed on the stack). With these properties, computation of any function in the system can be moved off to another processor with a separate memory space and Erlang will do this for you. Erlang only needs to replicate the arguments to the function and the results between the memory spaces (note: this would not be suitable for all kinds of applications...a function that needed to operate on a very large body of input state might present performance issues when replicating that state).
A naive use of threads in a C++ application might have different processors (in a multi-core system) trying to access the same shared memory at the same time. The system then has to do a lot of work to make sure the local caches associated with each core remain consistent. This is where you can suffer huge performance hits. We have an application at work that degrades in performance when you have more than a couple cores for this very reason. In fact, I'd go so far as to say you'd be better off to design your applications to only use threads where you need to do asynchronous I/O, but where you need to have processes doing real work and not blocked for I/O, use full processes. By using full processes, you guarantee that each process has it's own memory space and no two threads will use the same memory at the same time (of course, you then need to come up with a good means of communicating between those processes). With a system like this and a discipline around managing state and distributing processing, you could achieve similar results to what Erlang provides, but you have to do a lot of infrastructure stuff that Erlang already does for you.
It comes down to threads versus processes.
Operating systems were specifically designed so that each 'user' thought they had the whole computer to themselves - which is why you run apache as user wwwrun for instance.
Programmers, being programmers, started overloading that paradigm, first by each human user running multiple 'jobs'. Because operating systems were designed for multiple users, the upper scaling limit of that architecture reflected the upper scaling limit for logged in users - which is why apache, for instance, will start dying at 4,000 - 8,000 users.
Processes are a mature paradigm (my process can't crash yours). When we start seeing the introduction of threads though, things start getting very different. Here we have programmes that have external blocking activities (waiting on disk, waiting on io, waiting on memory) wanting to be able to wait on the one hand, and work on the other and threads allow you to do this and overcome two problems:
you can't get enough processes because the operating system can't handle it
each process is expensive because, by design, it gives the 'user' the full power of the operating system
The problem with threads is that they break the separation that processes were designed for. My thread can trash your thread - errors propagate.
Where Erlang is different is in a number of respects. Joe Armstrong's PhD Thesis is called Making Reliable Distributed Systems In The Presence Of Software Errors.
Reliability means processes are better than threads. The problem is that operating systems processes are too 'expensive' because they are designed for humans (you own the machine) and not concurrent units of programmes. In the Erlang VM, the VM has the full power of a multi-user system (it runs in an operating system process) and each Erlang process has a much smaller quantum of concurrent power - if it wants to use the 'big machine' it talks to the VM which does it for it. So Erlang processes are much cheaper than operating processes (and threads). You just spawn, spawn, spawn. Out of the box Erlang VM's start with 2**8 processes, but you can bump that up to millions (if you have enough RAM).
Also, as Joe put it in the first part of the first Section of his PhD Thesis, to have reliable software you need to start with two computers. With Erlang/OTP, at write time you don't know which computer your software will be running on. The Erlang/OTP cluster, at run time, will allocate your computational work. So an Erlang process is native distributed, as is spawn() (Erlang for fork()) and restart semantics.
Because Erlang has its own processes, it has its own scheduler and its own code loader/binary format (Erlang can be interpreted or it can compile to native binaries). This then gives a squad of additional benefits - before you write your Erlang/OTP application it can already hot swap its binaries out, etc, etc
So, sure you can write multi-threaded apps in C++ - but it is your responsibility to prevent error propagation and build system stability.
And sure, you can build reliable software in C - look at Erlang (the VM is written in C) the point is why would you want to? In the olden days, companies wrote their own 'operating systems', you could write your own operating system now, but why would you want to? There are millions of lines of robust tested code that 'does it', just like there is 1.5m lines of robust tested code in the Erlang/OTP system that 'does it'.
Using Erlang is about using the things that other people have written and only building the bits that make your company effective.
Context switch is extremely expensive. There are none in Erlang.
Locks makes traditional programs start to think which thread is going to execute next. That is also extremely expensive.
Gordon Guthrie's answer is great. Where is bigger difference is personal preference. From my point of view bigger difference in Erlang is reliability and serendipitous scalability. In Erlang you can design concurrent processes in natural manner without big performance issues and this will be serendipity scalable a distributable. There are pitfalls in big messages and so but in most cases your design will be elegant and performs well without especial care. When your design is elegant you make less mistakes, it will be better manageable and incidentally you can distribute and scale with minimal effort and result will be reliable.
To be brief, in Erlang you can design your program differently than in C++ because you can do it without big performance issue and promises good scalability and reliability without big effort. Nobody's perfect but for interestingly big amount of tasks Erlang is best choice.
Edit: Nice presentation about difference between Erlang and C++ - Erlang 2.5x bigger top performance, 3x less latency and 18x less SLOC - I assume that Motorola's developers are experienced in C++ enough to write good software.
Well, the nature of the language with variables that can only be set once and the fact that it's a functional language automatically makes programs with lots of parallelism be written and executed "the right way" for multicore.
I don't know much about erlang besides those two facts, so there might be something else too. But that's not to say you can't make a C++ program as scalable, but you'll probably go through a lot to achieve the performance, scalability and stability which will come with no cost if you write in erlang.