昨天的例子是透過erlang shell 傳遞要求給process.<br />
今天改為client server 方式.<br />
<br />
<pre name="code" class="c">
-module(e1014s).
-export([loop/0, rpc/2]).
loop() ->
receive
{From, {arale}} ->
From ! "She is 139 cm tall",
loop();
{From, {doraemon}} ->
From ! "He is 129.3 cm tall",
loop();
{From, Other} ->
From ! {error, Other},
loop()
end.
%
rpc(Pid, Request) ->
Pid ! {self(), Request},
receive
Response ->
Response
end.</pre><br />
<br />
編譯及執行:<br />
<br />
<pre name="code" class="c">
1> c(e1014s).
{ok,e1014s}
2> Pid = spawn(fun e1014s:loop/0).
<0.44.0>
3> e1014s:rpc(Pid, {arale}).
"She is 139 cm tall"
4> e1014s:rpc(Pid, {doraemon}).
"He is 129.3 cm tall"
5> e1014s:rpc(Pid, {ironman}).
{error,{ironman}}</pre><br />
<br />
loop/0擔任Server,rpc/2擔任Client.<br />
但是spwan是在erlang shell裡產生的,<br />
而且rpc對receive的部份,並未傳送進來<br />
process id (pid)做模式比對,當上面的<br />
程式進行中時,我們也可以透過其他process<br />
傳送message給他.<br />
<br />
接著來看進化的版本.<br />
<br />
<pre name="code" class="c">
-module(e1014t).
-export([loop/0, rpc/2]).
loop() ->
receive
{From, {arale}} ->
From ! {self(), "She is 139 cm tall"},
loop();
{From, {doraemon}} ->
From ! {self(), "He is 129.3 cm tall"},
loop();
{From, Other} ->
From ! {self(),{error, Other}},
loop()
end.
%
rpc(Pid, Request) ->
Pid ! {self(), Request},
receive
{Pid, Response} ->
Response
end.</pre><br />
<br />
編譯及執行:<br />
<br />
<pre name="code" class="c">
1> c(e1014t).
{ok,e1014t}
2> Pid=spawn(fun e1014t:loop/0).
<0.40.0>
3> e1014t:rpc(Pid, {arale}).
"She is 139 cm tall"</pre><br />
<br />
程式還需要再次進化,spawn還透過erlang shell協助.<br />
接著來看再次進化的版本.<br />
<br />
<pre name="code" class="c">
-module(e1014u).
-export([start/0, rpc/2]).
%% use start/0
start() ->
spawn(fun loop/0).
%%
loop() ->
receive
{From, {arale}} ->
From ! {self(), "She is 139 cm tall"},
loop();
{From, {doraemon}} ->
From ! {self(), "He is 129.3 cm tall"},
loop();
{From, Other} ->
From ! {self(),{error, Other}},
loop()
end.
%%
rpc(Pid, Request) ->
Pid ! {self(), Request},
receive
{Pid, Response} ->
Response
end.</pre><br />
<br />
編譯及執行:<br />
<br />
<pre name="code" class="c">
1> c(e1014u).
{ok,e1014u}
2> Pid=e1014u:start().
<0.40.0>
3> e1014u:rpc(Pid, {arale}).
"She is 139 cm tall"</pre><br />
<br />
接著來看產生一個process需要花費多少時間<br />
<br />
<pre name="code" class="c">
-module(processes).
-export([max/1]).
%% 產生大量processes,測量時間後取平均
%% wait/0, for/3 供 max/1 使用
max(N) ->
Max = erlang:system_info(process_limit),
io:format("Maximum allowed processes:~p~n", [Max]),
statistics(runtime),
statistics(wall_clock),
% spwan pid store in List L
L = for(1, N, fun() -> spawn(fun() -> wait() end) end),
{_, Time1} = statistics(runtime),
{_, Time2} = statistics(wall_clock),
% Destroy processes
lists:foreach(fun(Pid) -> Pid ! die end, L),
U1 = Time1 * 1000 / N,
U2 = Time2 * 1000 / N,
% Display spawn time
io:format("Process spawn time=~p (~p) microseconds~n", [U1, U2]).
%%
wait() ->
receive
die -> void
end.
%%
for(N, N, F) -> [F()];
for(I, N, F) -> [F() | for(I+1, N, F)].</pre><br />
<br />
編譯及執行:<br />
<br />
<pre name="code" class="c">
1> c(processes).
{ok,processes}
2> processes:max(20000).
Maximum allowed processes:262144
Process spawn time=3.5 (3.5) microseconds
ok
3> processes:max(20000).
Maximum allowed processes:262144
Process spawn time=2.5 (2.95) microseconds
ok</pre><br />
<br />
我們啟動erl時,並未指定增加可以生成processes的限制,<br />
此程式一併顯示出限制值為 262144,<br />
產生20000個processes的情形下, 平均每個的cpu時間與wall-clock<br />
都很短.<br />
<br />
接著啟動erl時使用 +P 參數, 設定為 500000.<br />
產生50000進行測試.<br />
<br />
<pre name="code" class="c">
erl +P 500000
Erlang/OTP 17 [erts-6.2] [source-5c974be] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V6.2 (abort with ^G)
1> processes:max(50000).
Maximum allowed processes:524288
Process spawn time=3.6 (3.04) microseconds
ok
2> processes:max(50000).
Maximum allowed processes:524288
Process spawn time=3.6 (3.06) microseconds
ok</pre><br />
<br />
時間還是很短.