2008-12-16 [長年日記]

[Rails] Metal

Rails edge に Metal という新しい機能が追加された。これは Rack を用いた高速な Controller であり、Rails の色んな機能は捨ててでも、兎に角、単純で速いレスポンスがどうしても必要だ!という局面ではもの凄い助けになるだろう。

http://github.com/rails/rails/commit/8c3a54366435eebc2c8aa63b63e1349ce74a7b38

作成

場所は app/metal。metal ジェネレータが用意されているので、controller と同じ感覚で使える。既存のコントローラ(top1)と速度比較をするので、こちらの名前はtop2にしてみる。

% ruby script/generate metal top2
      create  app/metal
      create  app/metal/top2.rb

従来のコントローラ的思想でいけば top2_metal.rb が作成されそうなものだが、そうはなっていない。この辺あたりに Merb 臭が少し見え隠れする気がするし、最近 DHH が Merb を意識してきる説を裏付ける一説になりえるかもしれない。とは言え、数時間前に生まれたばかりの機能だし、Rails的にはディレクトリ名にも app/metals じゃねーの?という気もするので、この辺は今後変わりうるだろうから気にしないでおこう。

Metalファイル

余談はおいといて、早速中身を見てみる。

app/metal/top2.rb

# Allow the metal piece to run in isolation
require(File.dirname(__FILE__) + "/../../config/environment") unless defined?(Rails)

class Top2 < Rails::Rack::Metal
  def call(env)
    if env["PATH_INFO"] =~ /^\/top2/
      [200, {"Content-Type" => "text/html"}, "Hello, World!"]
    else
      super
    end
  end
end

route も兼ねた、本当にシンプルな HTTP Response 生成機になっている。そして、冒頭のコメントとコードが示す通り、Rails とは隔離したスタンドアローンとして起動することもできるのだ。

rackup

Rails と切り離して Rack アプリ(ウェア?)として立ち上げる場合は、rackup コマンドを利用する。もし入ってなければ、gem install rack すべし。

% rackup --version
Rack 0.1

rackup に metal ファイルを渡せば Rack によるWebサーバが起動する。デフォルトでは9292ポートが利用されるようだ。覚えにくいので、「クニクニしちゃうわ〜」と歌いながらアクセスしてみる。

% rackup app/metal/top2.rb & 
% w3m http://localhost:9292/top2
Hello, World!

ちゃんと動いてる。

速度比較 (development)

さて、いよいよ爆速と歌われるその実力を確認する時間だ。名前的には順序が逆になるが、比較対象となる通常のコントローラ(top1)を作成する。アクションは同等の render :text にする。

% ruby script/generate controller top1
% vi app/controllers/top1_controller.rb
class Top1Controller < ApplicationController
  def index
    render :text=>"Hello, Rails!"
  end
end

rackup のデフォルトサーバは Mongrel なので、こちらも Mongrel で起動。(環境は development)。top1は当て馬なので、なるべく低いスコアを期待するところ大である。

% ab -n 1000 http://localhost:3000/top1
...
Requests per second:    55.08 [#/sec] (mean)

Mongrel でも development だと、こんな遅かったっけ?とりあえず、次は Metal (via rackup:Mongrel) を試す。rackup でそのまま起動すると、アクセスログが表示されてしまうので、-D でデーモン起動してみる。

% rackup -D app/metal/top2.rb
% ab -n 1000 http://localhost:9292/top2
...
Requests per second:    482.86 [#/sec] (mean)

なんと約10倍!うーん、なんか出来すぎてる。やっぱり production モードで試さないとね。

(※編集部注: 記事初出時、性能比算出を誤って「約100倍!」と記載しておりました。訂正および計算ドリル100回ノルマを課させていただきます。関係者の皆さまには御迷惑をお掛けしましたことお詫び申し上げます。)

速度比較 (production)

Controller(top1) 用の Mongrel を production で起動し直して、再度計測。

% ab -n 1000 http://localhost:3000/top1
...
Requests per second:    556.38  [#/sec] (mean)

ですよねぇ。Mongrel はやれば出来る子。ここで、

Rails+Controller(production) ≒ Rack+Metal(development)

という図式を得た。後は、Metal(production) が抜群の成績を残せば大団円で、「Metalスゲー!」と人に奨め易くなるもの。さあ、Metal 選手、ここからは自分との戦いです。どこまで記録を伸ばせるか。自らの手で栄冠をつかみ取れ!

% rackup -D --env production app/metal/top2.rb
% ab -n 1000 http://localhost:9292/top2
...
Requests per second:    516.86 [#/sec] (mean)

なにこれ。期待倒れ、つーか、しょっぺーwww。とりあえず、これまでの成績をまとめてみる。

ServerResponderdevelopmentproduction
Rails+MongrelController55556
Rack+MongrelMetal482516

もう既に render :text レベルなら Rails + Mongrel + production で理論値ってこと?

Rails 内での速度比較

ここで、rackup および Rack::Mongrel がまだこなれていない(足かせになっている)可能性に気付いた。スタンドアローン Metal でなく、Rails + Metal で試してみる。

# Mongrel(development)
% ab -n 1000 http://localhost:3000/top2
Requests per second:    1690.79 [#/sec] (mean)

# Mongrel(production)
% ab -n 1000 http://localhost:3000/top2
Requests per second:    1706.47 [#/sec] (mean)

うお、はえーっ!!!development と production で違いが現れないのは、Metal が reloadable (死語)でないため。(今気付いた)。てことで、さっきの Rack+Mongrel での数値も何度もやれば逆転or等しくなる可能性が高い。ついでに、Thin でも比較してみた。

ServerResponderdevelopmentproduction
Rails+MongrelController55556
Rack+MongrelMetal482516
Rails+MongrelMetal16901706
Rails+ThinController56636
Rails+ThinMetal27242524

Rails+Thin で production の方が遅いのはご愛嬌。前述の理由で両方計測するのは本当は無意味だろうし(同じだから)、Rails+Thin は計測の度に1800-2700程度を行き来して安定しないので、おおよそRubyなCGIでの限界値に近づいているのかもしれない。

[Rails] Metalの戦闘力

Metal では現在のところ production = development だと仮定して、それらの平均を取って全体の戦闘力をグラフで表してみる。

Rails+Thin+Metal 2624
Rails+Mongrel+Metal 1698
Rails+Thin+Controller [pro] 636
Rails+Mongrel+Controller [pro] 556
Rack+Mongrel+Metal 499
Rails+Thin+Controller [dev] 56
Rails+Mongrel+Controller [dev] 55

Metal いいね!遅さが難点だったRailsには嬉しい機能だ。そして、これからのREST時代、外部にまぁ見られてもいい(or認証不要な)マスタ情報を高速に取得するためのデバイスとして重宝しそう。例えば、住所情報のautocompleteの受け口のアクションとかね。あと、そろそろ Mongrel 卒業して、Thin 使えってことか。あと、Rails の Rack::Mongrel アダプタがんがれ!

本日のツッコミ(全4件) [ツッコミを入れる]
_ masuidrive (2008-12-17 08:28)

Metal〜?<br>速度の為にRails捨てて、EventMachineで全部組み直している私は負け組?

_ shio (2008-12-17 09:33)

そうそう、アイリスオーヤマのメタルラックはなかなか良いですね。

_ paco (2008-12-17 15:19)

rails一本で何も考えずにスタートしても後で何とかなるって安心感は増えますねー<br><br>んなこたぁーない。守備範囲はかぶりません。期待してますー>masuidrive

_ 舞波 (2008-12-18 08:57)

EventMachineで全国制覇!?結構、結構!<br><br>はいあがろう!!「負けた事がある」という事はいつか大きな財産になる


サイト内検索 (by Google)

| JRuby | Rails | Berryz | ℃-ute | エッグ | jQuery |

過去

2008年
12月
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

未来

コンタクト