
What's all this fuss about Erlang?
- Transfer
No one is able to predict the future - but I will make some reasonable assumptions.
Suppose Intel is right that their Keifer project will fire. If this happens, then 32-core processors will appear on the market no later than 2009-2010.
There is nothing surprising here. Sun already sells eight-core Niagara with 4 “hyperthreads” on each core, equivalent to 32-core cores.
This is a development that will make Erlang programmers happy. They have been waiting for this event for 20 years, and now the time has come for reckoning.
Good news for Erlang programmers:
On an N-core processor, your program will run N times faster.
Is this true?
Nearly. It is still too early to talk about this, but we are optimistic (wildly optimistic - I have not seen such optimism in the last 20 years!).
In some cases, you will have to tweak your code a little bit - when I ran my documentation program for generating Erlang on Sun Niagara (equivalent to a 32-core processor), the changes affected only one line of code (changed map to pmap - I apologize for the details. pmap is just a “parallel map”).
The program (which generated 63 documents from the wiki layout) began to work 7 times faster. Not 32 times, of course - but, I assure you, much faster (it later turned out that the disk I / O was a bottleneck, and since it was not parallelized, we ran into a sevenfold increase :).
In Ericsson, where I worked, and where Erlang was developed, we port some applications to 4-core processors - and you know what? After light doping, they work almost 4 times faster. We don’t have enough patience to wait for the 80-nuclear stones that Intel plays with in laboratories ...
So why do our programs work so quickly with such simplicity? It's all about a variable state and concurrency.
Variables and Concurrency
From ancient times (wild 20 years ago), there are two models of parallelism:
- With shared memory (
message passing)
Since then, the whole world has gone one way (shared memory), but we chose another.
Only a very small number of languages followed the path of concurrency on messaging - for example, Oz and Occam.
Speaking of concurrency in messaging, we postulate: "There is no shared memory." All calculations are performed in isolated processes and the only way to exchange information is asynchronous messaging.
So what is it good for?
Shared memory parallelism is built on the principle of “mutable state” (literally, memory that can be changed). All languages like C, Java, C ++, etc. carry the concept of "memory", which we can change.
This is only good if exactly one process is producing changes.
But if you have several processes dividing one memory and changing it, then the shaped nightmare begins.
To prevent simultaneous writing to shared memory, we need a locking mechanism. Call it a mutex or a synchronized method, but call it whatever you want - it will remain a lock.
If a program crashes in a critical region (that is, at the time when blocking is enabled), then this is a disaster. All other programs do not know what to do.
How do programmers solve these problems? They are praying. On a single-core processor, their programs can "just work", but on a multi-core, everything falls.
There are different ways to prevent this ( transactional memory is probably the best way), but there will still be blunders, and in the worst case, a nightmare.Erlang has no mutable data structures
(generally speaking, there is, but it doesn’t matter)
No mutable data → no locks.
No changeable data -> easy to parallelize.
So how do we parallelize? Easy - the programmer splits the solution to several parallel processes.
This programming style is called ...
(drum roll)Concurrency orientated programming
Erlang is not about objects. He has his own metaphor.Objects are not in fashion. Meet concurrency.
The world is parallel. A bunch of events are happening around us at the same time. I would not be able to drive my car along the highway without understanding the principle of parallelism on an intuitive level - pure parallelism in messaging, which is what we live by.
Imagine a group of people. They have no general condition.
I have my own personal memory (in my head), and you have your own. And she is not common. We communicate by transmitting messages (light and sound waves). We update our internal state based on the perception of these signals.
This is what concurrent programming is at its core.
It’s as if we are hiding a mutable state inside an object - the very property that makes paralleling impossibly difficult a problem.And does it work?
Yes. Erlang is used worldwide in high-tech projects where reliability is required. The flagship Erlang project, developed by Ericsson, a Swedish telephone company, is the AXD301 switch. There are more than two million lines of Erlang in it.
AXD301 - this is nine nines of reliability (yes, your eyes do not deceive you - 99.999999999%). Five nines are considered a good indicator (downtime - 5.2 minutes per year). Seven nines are almost unattainable ... but we managed to reach 9.
Whereby? Lack of shared memory plus an advanced crash recovery model. You can read more about all this in my Ph.D. dissertation .Erlang users?
- those who are “in the know”
Ericsson wings
start-ups , ejabberd 3D-modeling program , IM-server for jabber / XMPP tsung, multi-protocol tool for distributed load testing yaws, high-performance web server for thousands of hackers dreaming: “I wish I could get it on my office work ”Is Erlang complicated?
Not. But he is unusual .
Erlang does not have a "C-like syntax to make it easier to learn." It is not “object oriented,” it does not have “variables,” and it is a “functional programming language.”
This is all very unfriendly garbage - and, after a superficial acquaintance, scaring away new users. But the funny thing is that in fact it is a very small and simple language.
You probably already wondered what the Erlang code looks like. The language assumes the widespread use of the pattern matching syntax — here is a small example of Erlang code (taken from a new book about it):-module (geometry).
-export ([area / 1]).
area ({rectangle, Width, Ht}) -> Width * Ht;
area ({square, X}) -> X * X;
area ({circle, R}) -> 3.14159 * R * R.
Compile it and run it in the Erlang shell:1> c (geometry).
{ok, geometry}
2> geometry: area ({rectangle, 10, 5}).
50
3> geometry: area ({circle, 1.4}).
6.15752
In general, it’s easy ... Here is the Java code that does the same:abstract class Shape {
abstract double area ();
}
class Circle extends Shape {
final double radius;
Circle (double radius) {this.radius = radius; }
double area () {return Math.PI * radius * radius; }
}
class Rectangle extends Shape {
final double ht;
final double width;
Rectangle (double width, double height) {
this.ht = height;
this.width = width;
}
double area () {return width * ht; }
}
class Square extends Shape {
final double side;
Square (double side) {
this.side = side;
}
double area () {return side * side; }
}
From a translator : Erlang code that creates two processes ping and pong, pinging each other several times:-module (pingpong).
-export ([start / 0, ping / 2, pong / 0]).
ping (0, Pong_PID) ->
Pong_PID! finished,
io: format ("ping finished ~ n", []);
ping (N, Pong_PID) ->
Pong_PID! {ping, self ()},
receive
pong ->
io: format ("Ping received pong ~ n", [])
end,
ping (N - 1, Pong_PID).
pong () ->
receive
finished ->
io: format ("Pong finished ~ n", []);
{ping, Ping_PID} ->
io: format ("Pong received ping ~ n", []),
Ping_PID! pong,
pong ()
end.
start () ->
Pong_PID = spawn (pingpong, pong, []),
spawn (pingpong, ping, [3, Pong_PID]).
Conclusion:1> c (pingpong).
{ok, pingpong}
2> pingpong: start ().
<0.36.0>
Pong received ping
Ping received pong
Pong received ping
Ping received pong
Pong received ping
Ping received pong
ping finished
Pong finishedWhere can I get Erlang?
Download it from erlang.org
Note translator: a bunch of links from the end of the original article
- those who are “in the know”
Ericsson wings