by Joe ArmstrongNo one is able to predict the future - but I will make some reasonable assumptions.
Suppose that Intel is right that their project Keifer will shoot. If this happens, then 32 nuclear processors will appear on the market no later than 2009-2010.
')
There is nothing surprising here. Sun is already selling eight-core Niagara with 4 “hyperthreads” on each core, which is equivalent to 32 cores.
This is a development that will make happy Erlang programmers. They have been waiting for this event for 20 years, and now the time has come to pay.
Good news for Erlang programmers:
On an N-core processor, your program will run N times faster.
Is this true?
Nearly. So far it is still too early to talk about it, 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 bit - when I ran my Erlang documentation generation program on Sun Niagara
(equivalent to a 32 core processor) , the changes affected only one line of code
(changed map to pmap - I apologize for those details pmap is just a "parallel map") .
The program
(which generated 63 documents from the wiki markup) began to work 7 times faster. Not 32 times, of course - but, I assure you, much faster
(later it turned out that the disk I / O was a bottleneck, and since it was not parallelized, we rested on 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 a light finish, they work almost 4 times faster. We already have not enough patience to wait for the 80-core stones with which Intel is played in laboratories ...
So why do our programs run faster with such simplicity? It's all about changeable state and parallelism.
Variables and concurrency
C ancient times (wild 20 years ago) there are two models of parallelism:
- Shared memory
On messaging (message passing)
Since then, the whole world went one way (shared memory), and we chose another.
Only a very small number of languages ​​took the road of parallelism in the exchange of messages - 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?
Parallelism with shared memory is based on the principle of "changeable state" (literally - a memory that can be changed). All languages ​​like C, Java, C ++, etc. carry the concept of "memory" that we can change.
This is good only if there is exactly one process making 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 lock mechanism. Call it a mutex or synchronized method, and whatever you want, call it - it will remain a lock.
If a program crashes in a critical region (i.e., while the lock is on), then this is a disaster. All other programs do not know what to do.
How do programmers solve these problems? They pray. On a single-core processor, their programs can “just work”, but on a multi-core processor, everything falls.
There are various ways to prevent this ( transactional memory is probably the best way), but there will still be bloopers, and in the worst case, a nightmare.
Erlang has no variable data structures.
(generally speaking, there is, but it does not matter)
No changeable data → no locks.
No changeable data → easy to parallelize.
So how do we parallelize? Easy - the programmer breaks the solution of the problem into several parallel processes.
This programming style is called ...
(drumroll)
Concurrency Oriented Programming
Erlang is not about objects. He has his own metaphor.
Objects are not in vogue. Meet the parallelism.
The world is parallel. A bunch of events happening around us all at once 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 the exchange of messages, which is what we live.
Imagine a group of people. They have no general condition.
I have my own personal memory (in my head), and you have my own. And it 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 parallel programming is in its essence.
It is as if we are hiding the changeable state inside the object - the very property that makes the parallelization to impossibly difficult problem.
And does it work?
Yes. Erlang is used worldwide in high-tech projects where reliability is required. The flagship project on Erlang, developed by Ericsson, by the Swedish telephone company is the AXD301 switch. There are more than two million Erlang lines in it.
AXD301 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 practically unattainable ... but we managed to reach 9.
Whereby? Lack of shared memory, plus an advanced model of crash recovery. You can read about all this in more detail in my Ph.D. thesis .
Erlang users?
- those who are "in the subject"
startups
Ericsson
wings , a program for 3D-modeling
ejabberd, IM server for jabber / XMPP
tsung, a multiprotocol tool for distributed load testing
yaws, high-performance web server
Thousands of hackers dreaming: “I wish I could use it at my office work”
Is Erlang complicated?
Not. But he is unusual .
Erlang has no “C-like syntax to make learning easier.” It is not “object-oriented,” it has no “variables,” and it is a “functional programming language.”
This is all very unfriendly garbage - and, after a superficial acquaintance, scares new users. But the funny thing is that in fact - it is a very small and simple language.
You probably already wondered what the code on Erlang looks like. The language assumes the ubiquitous use of pattern matching syntax (pattern matching) - this 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 is easy ... Here is a Java code that does the same thing:
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 the translator : Erlang code that creates two ping and pong processes that ping 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 finished
Where can I get Erlang?
Download it from erlang.org
Note a translator: a bunch of links from the end of the original article