challenge 分散関数呼び出し

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

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

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

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

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

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

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

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

Posted feedbacks - OCaml

JoCaml は OCaml に並行プログラミングの概念の一つである join calculus のサポートを組み込んだ言語です。
並行プログラミングと分散プログラミングがサポートされています。

server.ml を動かした状態で client.ml を動かすことで、サーバ側に定義されている price_string 関数が 10000 回実行されます。

サーバ:
 Mac OS X 10.5 PPC G5/1.8GHz mem:1GB
クライアント:
 FreeBSD 6.2R Pen3/550MHz mem:256MB

という環境でテストしました。
まずインタプリタで、

 server% jocaml server.ml 10000
 listening address 10.0.1.5
 listening port 10000

 client% time jocaml client.ml 10.0.1.5 10000
 jocaml client.ml 10.0.1.5 10000  12.28s user 1.09s system 69% cpu 19.178 total

jocamlopt でネイティブコンパイルしたもので、

 server% ./server 10000

 client% time ./client 10.0.1.5 10000
 ./client 10.0.1.5 10000  4.84s user 1.17s system 60% cpu 9.930 total

といった感じでした。
実行される関数はサーバ側に定義されているので、実際の実行はサーバ側でされています。
それと、JoCaml では for 文が並行実行されるので、client.ml での price_string の呼び出しはおそらく直列には動いていません。
 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
65
66
67
(* server.ml *)

def price_string(value, discount) =
   let comma_sep () num =
      let str  = Printf.sprintf "%d" num in
      let len  = String.length str in
      let rec s_to_l r i =
         if i >= len then r
         else
            s_to_l (str.[i] :: r) (i + 1)
      in
      let str', _ =
         List.fold_left begin fun (s, i) ch ->
            match i with
            | 3 -> (ch :: ',' :: s, 0)
            | i -> (ch :: s, (i + 1))
         end ([], 0) (s_to_l [] 0)
      in
      List.fold_left begin fun acc ch ->
         acc ^ (String.make 1 ch)
      end "" str'
   in
   let new_value = value * (100 - discount) / 100 in
   let msg =
      Printf.sprintf "販売価格 %a円 (定価%a円から%d%%引き)"
                     comma_sep new_value comma_sep value discount
   in
   reply msg to price_string

let main () =
   match Sys.argv with
   | [|_; listen_port|] -> begin
        let addr = Join.Site.get_local_addr () in
        let addr_str = Unix.string_of_inet_addr addr in
        let sock = Unix.ADDR_INET (addr, int_of_string listen_port) in
        List.iter print_endline
           ["listening address " ^ addr_str;
            "listening port " ^ listen_port];
        Join.Ns.register Join.Ns.here "price_string" price_string;
        Join.Site.listen sock;
        at_exit Join.exit_hook
     end
   | _ ->
        print_endline "usage: command listen_port"

let () = if not !Sys.interactive then main ()


(* client.ml *)

let main () =
   match Sys.argv with
   | [|_; server_addr; server_port|] ->
        let addr = Unix.inet_addr_of_string server_addr in
        let sock = Unix.ADDR_INET (addr, (int_of_string server_port)) in
        let namespace = Join.Ns.there sock in
        let price_string : int * int -> string =
           Join.Ns.lookup namespace "price_string"
        in
        for i = 0 to 10000 do
           ignore (price_string (2000, 20))
        done;
        print_endline (price_string (2000, 20))
   | _ ->
        print_endline "usage: command server_address server_port"

let () = if not !Sys.interactive then main ()

Index

Feed

Other

Link

Pathtraq

loading...