2012-02-12 11 views
12

私は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ブロッキングスレッドには近づいていませんでした。

アイデア、コメント、そしてより良い実装のための提案は大歓迎です。

+1

テストに遠隔のサーバーを使用しないでください。待ち時間はさまざまです。あなたは、ファイバーを少なくして非同期テストをやり直すべきです.20本のファイバーは、正確なabラインを使って1000本のファイバーで1秒/リクエストに対して300ms /リクエストを得ます。あなたのスレッドサーバーは、既定では20スレッドの既定のイベントマシンスレッドプールを使用しています。 – Schmurfy

+0

確かに、ファイバープールのサイズを20に設定すると、実際に私の箱のパフォーマンスは低下します。 – BSM

+0

おそらく20ではなく1000が本当に高いです、私はローカルサーバーでテストしたので、応答時間は本当に低かったです。 – Schmurfy

答えて

2

「1回のリクエストあたりの時間」が「テストに要した時間」と完全に等しいかどうかを確認してください。これは、リクエストカウント(-n)が同時実行レベル(-c)と等しいために、レポートの算​​術演算結果です。 mean-timeは、合計時間*同時実行数/ num-requestsです。したがって、-n == -cが報告された平均は、最も長い要求の時刻になります。妥当な対策を講じるには、いくつかの要因によって-n> -cでab実行を行うべきです。

あなたはabの古いバージョンを比較的現状のものとして使用しているようですが、デフォルトでははるかに詳細な結果が報告されています。 Googleに対して直接実行すると、-n == -cの場合と同様の合計時間==平均時間が表示され、-n> -cの場合にはより合理的な数値が得られます。実際には、req/sec、すべての同時要求の平均、および最終的なサービスレベルの内訳を調べて、より理解を深める必要があります。

$ ab -c50 -n50 http://google.com/ 
This is ApacheBench, Version 2.3 <$Revision: 655654 $> 
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ 
Licensed to The Apache Software Foundation, http://www.apache.org/ 

Benchmarking google.com (be patient).....done 


Server Software:  gws 
Server Hostname:  google.com 
Server Port:   80 

Document Path:  /
Document Length:  219 bytes 

Concurrency Level:  50 
Time taken for tests: 0.023 seconds   <<== note same as below 
Complete requests:  50 
Failed requests:  0 
Write errors:   0 
Non-2xx responses:  50 
Total transferred:  27000 bytes 
HTML transferred:  10950 bytes 
Requests per second: 2220.05 [#/sec] (mean) 
Time per request:  22.522 [ms] (mean)  <<== note same as above 
Time per request:  0.450 [ms] (mean, across all concurrent requests) 
Transfer rate:   1170.73 [Kbytes/sec] received 

Connection Times (ms) 
       min mean[+/-sd] median max 
Connect:  1 2 0.6  3  3 
Processing:  8 9 2.1  9  19 
Waiting:  8 9 2.1  9  19 
Total:   11 12 2.1  11  22 
WARNING: The median and mean for the initial connection time are not within a normal deviation 
     These results are probably not that reliable. 

Percentage of the requests served within a certain time (ms) 
    50%  11 
    66%  12 
    75%  12 
    80%  12 
    90%  12 
    95%  12 
    98%  22 
    99%  22 
100%  22 (longest request)  <<== note same as total and mean above 


$ ab -c50 -n500 http://google.com/ 
This is ApacheBench, Version 2.3 <$Revision: 655654 $> 
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ 
Licensed to The Apache Software Foundation, http://www.apache.org/ 

Benchmarking google.com (be patient) 
Completed 100 requests 
Completed 200 requests 
Completed 300 requests 
Completed 400 requests 
Completed 500 requests 
Finished 500 requests 


Server Software:  gws 
Server Hostname:  google.com 
Server Port:   80 

Document Path:  /
Document Length:  219 bytes 

Concurrency Level:  50 
Time taken for tests: 0.110 seconds 
Complete requests:  500 
Failed requests:  0 
Write errors:   0 
Non-2xx responses:  500 
Total transferred:  270000 bytes 
HTML transferred:  109500 bytes 
Requests per second: 4554.31 [#/sec] (mean) 
Time per request:  10.979 [ms] (mean) 
Time per request:  0.220 [ms] (mean, across all concurrent requests) 
Transfer rate:   2401.69 [Kbytes/sec] received 

Connection Times (ms) 
       min mean[+/-sd] median max 
Connect:  1 1 0.7  1  3 
Processing:  8 9 0.7  9  13 
Waiting:  8 9 0.7  9  13 
Total:   9 10 1.3  10  16 

Percentage of the requests served within a certain time (ms) 
    50%  10 
    66%  11 
    75%  11 
    80%  12 
    90%  12 
    95%  13 
    98%  14 
    99%  15 
100%  16 (longest request) 
関連する問題