프로그래밍의 판도가 변하고 있다. 고성능 단일 프로세서는 서서히 멸종되어 가고 있다. 오늘날, 그리고 미래의 대세는 멀티코어, 분산처리 시스템이다. 얼랑(Erlang)은 이러한 환경에서 신뢰성(reliability), 유지보수성(maintainability), 확장성(scalability)이 있는 코드를 작성하기에 용이한 프로그래밍 언어다. - Programming Erlang 중에서...전 직장 팀장님께서, 관리하던 시스템의 개선안 중 하나로 이상한 프로그래밍 언어를 언급하셨던 적이 있습니다. 왠 전화 통신 회사에서 만든 프로그래밍 언어가 있다는 말씀에 눈만 말똥거리다가 잊어버렸었는데 알고보니 그게 얼랑(Erlang)이었군요. 올해로 20주년을 맞이한 뼈대있는 언어로, 얼랑을 개발한
에릭슨(Erlang) 이외에 다른 회사들에서도 제품 개발에 이를 사용하고 있다고 합니다.
Programming Erlang 책을 읽다가 연습문제가 있길래 풀어보려 했으나, 함수형 프로그래밍에 생소한 제겐 너무 막막해서 검색을 했습니다. 그리고 서너개의 소스를 읽어보고 마음에 드는 코드들의 장점을 따서 고쳤습니다.
N개의 프로세스를 원형으로 연결하고, 그 고리를 통해 M개의 메시지를 전달하는 프로그램 입니다. 일반적인 환경에서는 스레드들을 생성해서 이벤트나 소켓으로 메시지를 주고받아야 하는데 얼랑 코드는 매우 간결하네요.
1 %%----------------------------------------------------------------------------- 2 %% File : ring.erl 3 %% Author : Junho Ryu 4 %% Created : December 01, 2007 5 %% 6 %% Trimmed version of joemomma's code 7 %% http://erl.nfshost.com/wordpress/2007/07/28/a-ring-benchmark-in-erlang/ 8 %% 9 %% Create N processes in a ring. Send a message round the ring M times so that10 %% a total of N * M messages get sent.11 %%12 %% - Problem 8.11 from Joe Amstrong's book, Programming Erlang13 %%-----------------------------------------------------------------------------14 15 -module(ring)
.16 -export([start
/2])
.17 18 start(N, M)
->19 StopwatchPid
= spawn(
fun()
-> stopwatch()
end),
20 HeadPid
= chain(N,
self()),
21 22 % io:format("loop ~p~n", [M]),23 HeadPid
! M,
24 25 pass(HeadPid, StopwatchPid)
.26 27 %%-----------------------------------------------------------------------------28 %% A stopwatch process. Starts when it is spawned, and stops when it receives29 %% any message30 %%-----------------------------------------------------------------------------31 stopwatch()
->32 statistics(
runtime),
33 statistics(
wall_clock),
34 receive35 _ ->36 {
_, Runtime}
= statistics(
runtime),
37 {
_, WallCock}
= statistics(
wall_clock),
38 io:format(
"~n~nCPU time=~p, Elapsed time=~p (ms)",
39 [Runtime, WallCock])
40 end.41 42 %%-----------------------------------------------------------------------------43 %% Construct a chain of processes, and return a PID of its head44 %%-----------------------------------------------------------------------------45 chain(
1, NextPid)
->46 NextPid;
47 chain(Length, NextPid)
->48 chain(
Length-1,
spawn(
fun()
-> pass(NextPid)
end))
.49 50 %%-----------------------------------------------------------------------------51 %% Pass every message to its next process. Repeat until it receives any number52 %% larger than 1.53 %%-----------------------------------------------------------------------------54 pass(NextPid)
->55 receive56 Number
->57 % io:format("pass ~p~n", [Number]),58 NextPid
! Number,
59 if60 Number
> 1 ->61 pass(NextPid);
62 true ->63 done
64 end65 end.66 67 %%-----------------------------------------------------------------------------68 %% Countdown a number that has been received from a tail process, and pass it69 %% to a head process. When a message of the last round arrives, send a message70 %% to a stopwatch process, and stop.71 %%-----------------------------------------------------------------------------72 pass(HeadPid, StopwatchPid)
->73 receive74 Countdown
when Countdown
=< 1 ->75 StopwatchPid
! done;
76 Countdown
->77 % io:format("~nloop ~p~n", [Countdown-1]),78 HeadPid
! Countdown
- 1,
79 pass(HeadPid, StopwatchPid)
80 end.