内部処理を並列化して応答性を改善してみよう。
それなりに時間のかかる処理をサーバーに投げた場合、時間のかかる処理を
逐次的に処理させると他のクライアントヘのレスポンスが低下します。
プロセルを使って内部処理を並列化して応答性を改善します。
フィボナッチ計算サーバーの内部処理を並列化します。
%%==============================
%% フィボナッチ数計算の内部処理を並列化(サーバー側)
%%==============================
cfibsvr() ->
receive
{0, Pid} when is_pid(Pid) ->
Pid ! 1,
cfibsvr();
{1, Pid} when is_pid(Pid) ->
Pid ! 1,
cfibsvr();
{X, Pid} when is_pid(Pid), X < 24 ->
Pid ! fib(X - 1) + fib(X - 2),
cfibsvr();
%% 内部処理の並列化
{X, Pid} when is_pid(Pid) ->
W = spawn(fib, wait_for_result, [Pid]),
spawn(fib, fib, [X,W]),
cfibsvr();
terminate -> terminate
end.
%% 計算結果を待つ関数(メッセージは引数のプロセスIDに返却する)
wait_for_result(Pid) ->
receive
Res -> Pid ! Res
end.
%%==========================
%% フィボナッチ計算を並列化(クライアント側)
%%==========================
cfibclt(X) ->
%% 登録プロセスを探す
IsALIVE = whereis(cfibsvr),
if
%% 登録されていない時
IsALIVE == undefined ->
%% cfibsvrを登録プロセスとして登録する
register(cfibsvr, spawn(fib, cfibsvr, []));
%% 登録されていればOK
true -> ok
end,
%% 別プロセスで結果を待つ専用のプロセスを作成する
W = spawn(fib, wait_for_cfibsvr, [X]),
%% 登録プロセスにメッセージを送信する。計算結果は待ち専用のプロセスに返してもらう
cfibsvr ! {X, W}.
%% 計算結果を待つ関数(引数Xと受信メッセージを表示するだけの関数)
wait_for_cfibsvr(X) ->
receive
Res -> io:format("fib(~p) is ~p~n", [X, Res])
end.