challenge 分散関数呼び出し

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

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

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

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

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

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

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

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

Posted feedbacks - Ruby

Rubyの分散処理の定番dRuby!
DRB_URIを書き換えることで別サーバでも可能。

まず
ruby 45.rb server
でサーバを立ち上げる。そのあと
ruby 45.rb
でクライアントの実行。

・呼び出し10000回にかかった時間 7.9秒
・サーバとクライアントのCPU・メモリ  Pentium4 2.66GHz / 1GB
・同一サーバ内での実行か別サーバでの実行か  同一サーバ
・言語のバージョン  Ruby 1.8.5
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
require 'drb'
DRB_URI = "druby://localhost:2323"

if ARGV.first == 'server'
  obj = Object.new
  def obj.pricestring(price, cut_rate)
    comma = lambda{|n| n.to_s.reverse.scan(/\d{1,3}/).join(",").reverse}
    "販売価格 %s円 (定価%s円から%d%%引き)" % [comma[price*(100-cut_rate)/100], comma[price], cut_rate]
  end
  DRb.start_service DRB_URI, obj
  DRb.thread.join

else                            # client
  require 'benchmark'
  DRb.start_service
  obj = DRbObject.new(nil, DRB_URI)
  puts obj.pricestring(2000,20)
  puts Benchmark.measure { 10000.times{ obj.pricestring(2000,20)  } }.real
end

Rinda で実装してみました。
まず、ruby ts.rb でタプルスペースを起動します。タプルスペースは黒板みたいなものです。
次に ruby server.rb でサーバを起動。
最後に ruby client.rb でクライアントを起動します。
server.rb と client.rb の起動順は逆でもokです。
server.rb を複数個起動することもできます。もちろん複数プロセスで処理しますし、途中から起動してもokです。
# でも全然スケールしないですけど。

・10000回の実行結果
  ・サーバ1プロセス: 1分 (CPU 使用率 60%ぐらい)
  ・サーバ2プロセス: 1分 (同上)
   全然スケールしない。。。
・Intel Core Duo 1.66GHz、メモリ1G
・同一サーバ
・ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-mswin32]
 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
--[ts.rb]----------------------------------------

require 'rinda/tuplespace'

$ts = Rinda::TupleSpace.new
DRb.start_service('druby://:1234', $ts)
puts DRb.uri
DRb.thread.join

-- [server.rb] --------------------------------------

require 'rinda/tuplespace'

class Integer
  def commaize
    to_s.gsub(/(\d)(?=(?:\d\d\d)+(?!\d))/, '\1,')
  end
end

def pricestring(price, discount)
  "販売価格 %s円 (定価%s円から%d%%引き)" % [(price*(100-discount)/100).commaize, price.commaize, discount]
end

DRb.start_service
$ts = DRbObject.new_with_uri('druby://localhost:1234')
loop {
  req = $ts.take([:pricestring, nil, nil])
  price, discount = req[1..2]
  $ts.write([:pricestring_result, price, discount, pricestring(price, discount)])
  print "."
}

-- [client.rb] ---------------------------------------

require 'rinda/tuplespace'
require "benchmark"

DRb.start_service
$ts = DRbObject.new_with_uri('druby://localhost:1234')
puts Benchmark.measure {
  10000.times {
    $ts.write([:pricestring, 2000, 20])
    r = $ts.take([:pricestring_result, 2000, 20, nil])
    print "."
  }
}

Index

Feed

Other

Link

Pathtraq

loading...