challenge 分散関数呼び出し

分散関数呼び出しを実装してください.

呼び出される関数は,定価を整数で,割引率(%)を整数で受け取り,
文字列で「販売価格 ○円(定価○円から○%引き)」を返すものとします.
また,数字は3桁のカンマ区切りにするものとします.

たとえば,pricestring(2000, 20) なら
"販売価格 1,600円 (定価2,000円から20%引き)"
を返します.

関数の呼び出し元と,呼び出される側は,物理的に異なる
サーバに配置できることを条件とします.
呼び出し方法は問いませんが,呼び出し方法に名前がある場合,
それをタグに加えてください.
(XML-RPC,SOAP,CORBA,RMI,など)

また,作成した関数を直列に1万回呼び出して,
実行にかかった時間を測定してください.
測定時は別サーバでなくても構いません.
(なるべく別サーバが望ましいです)

測定環境として,
・サーバとクライアントのCPU・メモリ
・同一サーバ内での実行か別サーバでの実行か
・別サーバの場合,通信経路.(100Mbps Ethernet等)
・言語のバージョン
・ミドルウェアを使用している場合,その名前とバージョン
も併記してください.

1つの言語で複数の分散関数呼び出しの実装方法がある場合,
複数の回答を歓迎します.

出題の意図は,様々な分散呼び出し方法の実装例と,
レスポンス速度の確認にあります.
このお題は沢渡 みかげさんの投稿です。 まったく手を加えないでいい完成度の投稿で本当に助かります。 ありがとうございました。

Posted feedbacks - Erlang

普通にErlangのプロセス間通信を使って実装してみました.
夏休み中なのでとりあえず自宅マシンで測定.

・Intel(R) Xeon(R) CPU 5130  @ 2.00GHz
・同一サーバ内
・Erlang 5.5.4

で 1.04秒くらいでした.

Erlangのプロセス間通信は関数呼び出しの形になっていないので,
呼び出し側が引数をメッセージで送り,
それを受け取ったサーバが呼び出し側に戻値をメッセージで
送り返す形で実装しています.


サーバ側
> erl -noshell -name server@127.0.0.1 -s rcall_s start


クライアント側
> time erl -noshell -name client@127.0.0.1 -s rcall_c main -s init stop
remote pid <4053.36.0>
ret = bench_ok
1.044240 sec.

real    0m2.352s
user    0m0.908s
sys     0m0.156s
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
==== rcall_s.erl

-module(rcall_s).
-export([start/0, init/0]).

start() ->
  proc_lib:start(?MODULE, init, []),
  ok.

init() ->
  global:register_name(calc, self()),
  proc_lib:init_ack(ok),
  loop().

loop() ->
  receive
    {From, Price, Discount} ->
      From ! calc(Price, Discount)
  end,
  loop().


calc(Price, Discount) ->
  lists:flatten(io_lib:format("販売価格 ~s円(定価~s円から~w%引き)",
    [comma(Price * (100-Discount) div 100), comma(Price), Discount])).


comma([N1, N2, N3, N4 | RestN], Acc) ->
  comma([N4 | RestN], [",", N3, N2, N1 | Acc]);
comma(RestN, Acc) ->
  lists:flatten([lists:reverse(RestN), Acc]).

comma(N) when is_integer(N) ->
  comma(lists:reverse(integer_to_list(N)), []).


==== rcall_c.erl

-module(rcall_c).
-export([main/0, bench/2]).

main() ->
  init(),
  Pid = global:whereis_name(calc),
  io:format("remote pid ~w~n", [Pid]),
  {Time, Value} = timer:tc(?MODULE, bench, [Pid, 10000]),
  io:format("ret = ~w~n~f sec.~n", [Value, Time/1000000]).

init() ->
  net_adm:ping('server@127.0.0.1'),
  global:sync().
  % すぐにglobalnameが反映されないので,
  % pingしたあとsyncしてから利用する

bench(_, 0) ->
  bench_ok;
bench(Pid, N) ->
  % 送信元のPIDを知らせないと送り返せない
  Pid ! {self(), 2000, 20},
  receive
    _RetValue ->
      ok
  end,
  bench(Pid, N-1).

Index

Feed

Other

Link

Pathtraq

loading...