私はRuby(1.9.3-p0)で並行処理を行い、非常に単純なI/O処理の高いプロキシタスクを作成しました。まず、私は非ブロックアプローチを試してみました:Rubyの並行性:ノンブロッキングI/Oとスレッド
require 'rack'
require 'rack/fiber_pool'
require 'em-http'
require 'em-synchrony'
require 'em-synchrony/em-http'
proxy = lambda {|*|
result = EM::Synchrony.sync EventMachine::HttpRequest.new('http://google.com').get
[200, {}, [result.response]]
}
use Rack::FiberPool, :size => 1000
run proxy
=begin
$ thin -p 3000 -e production -R rack-synchrony.ru start
>> Thin web server (v1.3.1 codename Triple Espresso)
$ ab -c100 -n100 http://localhost:3000/
Concurrency Level: 100
Time taken for tests: 5.602 seconds
HTML transferred: 21900 bytes
Requests per second: 17.85 [#/sec] (mean)
Time per request: 5602.174 [ms] (mean)
=end
うーん、私は私が何か間違ったことしなければならないと思いました。ほとんどI/Oを待っているタスクの平均要求時間は5.6秒ですか?私は別のものを試しました:
require 'sinatra'
require 'sinatra/synchrony'
require 'em-synchrony/em-http'
get '/' do
EM::HttpRequest.new("http://google.com").get.response
end
=begin
$ ruby sinatra-synchrony.rb -p 3000 -e production
== Sinatra/1.3.1 has taken the stage on 3000 for production with backup from Thin
>> Thin web server (v1.3.1 codename Triple Espresso)
$ ab -c100 -n100 http://localhost:3000/
Concurrency Level: 100
Time taken for tests: 5.476 seconds
HTML transferred: 21900 bytes
Requests per second: 18.26 [#/sec] (mean)
Time per request: 5475.756 [ms] (mean)
=end
ちょっといいですが、私が成功と呼ぶものではありません。最後に、スレッド実装を試しました。
require 'rack'
require 'excon'
proxy = lambda {|*|
result = Excon.get('http://google.com')
[200, {}, [result.body]]
}
run proxy
=begin
$ thin -p 3000 -e production -R rack-threaded.ru --threaded --no-epoll start
>> Thin web server (v1.3.1 codename Triple Espresso)
$ ab -c100 -n100 http://localhost:3000/
Concurrency Level: 100
Time taken for tests: 2.014 seconds
HTML transferred: 21900 bytes
Requests per second: 49.65 [#/sec] (mean)
Time per request: 2014.005 [ms] (mean)
=end
これは本当に驚くべきことでした。私はここに何かを逃していますかEMはなぜここでひどくパフォーマンスしていますか?私は何か調整が必要ですか?私は様々な組み合わせ(ユニコーン、いくつかのRainbows設定など)を試しましたが、どれもシンプルで古いI/Oブロッキングスレッドには近づいていませんでした。
アイデア、コメント、そしてより良い実装のための提案は大歓迎です。
テストに遠隔のサーバーを使用しないでください。待ち時間はさまざまです。あなたは、ファイバーを少なくして非同期テストをやり直すべきです.20本のファイバーは、正確なabラインを使って1000本のファイバーで1秒/リクエストに対して300ms /リクエストを得ます。あなたのスレッドサーバーは、既定では20スレッドの既定のイベントマシンスレッドプールを使用しています。 – Schmurfy
確かに、ファイバープールのサイズを20に設定すると、実際に私の箱のパフォーマンスは低下します。 – BSM
おそらく20ではなく1000が本当に高いです、私はローカルサーバーでテストしたので、応答時間は本当に低かったです。 – Schmurfy