HTTP リクエストの性能比較をさまざまな Gem などで行ってみた。
net-http
一番標準的な Net::HTTP を使ってみる。
require "net/http"
100.times do
res = Net::HTTP.start("www.yahoo.co.jp") do |http|
http.get "/"
end
res.body
end
open-uri
みんな大好き open-uri も試してみる。
require "open-uri"
100.times do
body = open("http://yahoo.co.jp", &:read)
end
persistent_http
persistent_http を使ってみた。
require "persistent_http"
http = PersistentHTTP.new(
:name => "MyHTTPClient",
:pool_size => 3,
:pool_timeout => 5,
:warn_timeout => 0.25,
:force_retry => true,
:url => "http://www.yahoo.co.jp/"
)
100.times do
response = http.request
response.body
end
Net::HTTP (オブジェクト再利用)
標準ライブラリの Net::HTTP でオブジェクトを再利用したバージョン。
require "net/http"
Net::HTTP.start("www.yahoo.co.jp") do |http|
100.times do
res = http.get "/"
res.body
end
end
wget
意表を突いて、 Open3 + wget も試してみるテスト。
require "open3"
100.times do
stdout, stderr, exitcode = Open3.capture3("wget -d -O - http://www.yahoo.co.jp")
end
excon
excon を使ってみた。
リポジトリ中に Benchmark の実装もあるが、気にせず、独自に検証。
require "excon"
connection = Excon.new("http://www.yahoo.co.jp", persistent: true)
100.times do
get_response = connection.get(path: "/")
get_response.body
end
curb
libcurl を使った実装の1つ curb を使ってみた。
今回の実装では凝ったことをしてみた。
require "curb"
curl = Curl::Easy.new
urls = ["http://www.yahoo.co.jp/"] * 100
multi = Curl::Multi.new
responses = Hash.new do |hash, k|
hash[k] = ""
end
urls.each do |url|
curl = Curl::Easy.new url do |easy|
easy.on_body do |data|
responses[url] << data; data.size
end
end
multi.add curl
end
multi.perform do
end
urls.each do |url|
responses[url]
end
em-synchrony
EventMachine を使った実装の1つ em-synchrony を使ってみた。
require "em-synchrony"
require "em-synchrony/em-http"
require "em-synchrony/fiber_iterator"
urls = [ "http://www.yahoo.co.jp/" ] * 100
responses = Enumerator.new do |y|
EM.synchrony do
concurrency = 1
EM::Synchrony::FiberIterator.new( urls, concurrency ).each do |url|
y << [ url, EventMachine::HttpRequest.new(url).get ]
end
EventMachine.stop
end
end
responses.each do |url, response|
end
typhoeus
libcurl を使った実装の1つtyphoeus を使ってみた。
require "typhoeus"
100.times do
Typhoeus.get("www.yahoo.co.jp/")
end
httparty
なんとなく楽しそうな印象の HTTParty も使ってみた。
require "httparty"
100.times do
response = HTTParty.get('http://www.yahoo.co.jp/')
end
計測結果
実行時間は time コマンドで測定。
ファイル名 | 実行時間 |
---|---|
net-htp.rb | 11.712s |
open-uri.rb | 22.079s |
persistent-http.rb | 17.293s |
persistent-net-htp.rb | 16.401s |
wget.rb | 14.450s |
excon.rb | 25.299s |
curb.rb | 20.234s |
em-synchrony.rb | 8.906s |
typhoeus.rb | 8.909s |
httparty.rb | 12.472s |
Faraday 系の Gem は内部の Gem を直接使う場合に
比べて遅そうなので、試していません。
考察
たとえ concurrency が 1 でも、EventMachine を使う em-synchrony が最速という結果は少し意外でした。
実行タイミングによる差も非常に大きく、時間帯によっては上記の 2倍くらいの時間となることもあるので、上記の結果の信頼性はかなり低いです。
また www.yahoo.co.jp ではなく、もっと違う WEB サーバで試すべきかもしれません。
ただし、やっていることはほとんどアタックなので、自重しましょう。
私の中では
- 安定した実行性能(実行時間の標準偏差が小さいこと)
- 手馴れていること
- 異常時のデバッグログ取得などもやりやすいこと
- コード量も短くなること
などから wget を Open3 で実行した結果を使うことにしました。
ちゃんちゃん。
追記
コメントをいただいたので、追加で typhoeus を試してみました。さらについでに HTTParty も試してみました。
typhoeus は速いですね。
機能も豊富そうな上に API も簡単で試してみる価値ありそうです。