さくらのレンタルサーバーのRuby on Railsを高速化する方法
以前、さくらのレンタルサーバーにRuby on Railsをインストール、動作を確認し、実際に簡単なアプリケーションをうごかしてみました。
しかし、これがどうにも遅い! 通常はApacheに加えてfastCGI等を利用して起動の高速化をはかるのですが、さくらの共用サーバーでは利用できません(参考文献[1])。ただのCGIで動かした場合にどれぐらい遅いかというと、参考文献[2]をごらんください。普通の(?)方法でうごかすのと比較すると、ただのCGIはざっと100倍ぐらい遅い。ひどい!というわけで、多少でもはやくならんもんかと思い色々と試してみました。速度の測定にはhttperfを使ってみました[3]。Mac OS X の場合はMacPortsで簡単にインストール可能です。ほかのプラットフォームでもいろいろあると思いますが、割愛します。
まずは、RailsもRubyも関係ない、静的ファイルの場合を測定してみます。ファイルの内容はあとで出てくるRailsのものとおなじです。
% httperf --server=narak.sakura.ne.jp --port=80 --uri=/test.html --num-conns=100 --num-calls=1 httperf --client=0/1 --server=narak.sakura.ne.jp --port=80 --uri=/test.html --send-buffer=4096 --recv-buffer=16384 --num-conns=100 --num-calls=1 httperf: warning: open file limit > FD_SETSIZE; limiting max. # of open files to FD_SETSIZE Maximum connect burst length: 1 Total: connections 100 requests 100 replies 100 test-duration 8.095 s Connection rate: 12.4 conn/s (80.9 ms/conn, <=1 concurrent connections) Connection time [ms]: min 77.5 avg 80.9 max 88.4 median 80.5 stddev 2.2 Connection time [ms]: connect 27.0 Connection length [replies/conn]: 1.000 Request rate: 12.4 req/s (80.9 ms/req) Request size [B]: 78.0 Reply rate [replies/s]: min 12.2 avg 12.2 max 12.2 stddev 0.0 (1 samples) Reply time [ms]: response 27.3 transfer 26.6 Reply size [B]: header 231.0 content 5512.0 footer 0.0 (total 5743.0) Reply status: 1xx=0 2xx=100 3xx=0 4xx=0 5xx=0 CPU time [s]: user 1.83 system 6.17 (user 22.7% system 76.2% total 98.9%) Net I/O: 70.2 KB/s (0.6*10^6 bps) Errors: total 0 client-timo 0 socket-timo 0 connrefused 0 connreset 0 Errors: fd-unavail 0 addrunavail 0 ftab-full 0 other 0
httperfは指定のサイトの指定のページにある回数アクセスして、速度を測定します。今回は100回にしてみました。結果が色々出てますが、とりあえず
Request rate: 12.4 req/s (80.9 ms/req)ここだけみることにします。これは1リクエストあたり80.9msかかり、1秒間に12.4リクエストの処理が可能ということです。Railsの処理時間をいくらみじかくしても、これより速くなることはないという値です。
ではつぎに、サンプルのtodoリストの速度を測定してみます。
Request rate: 0.5 req/s (1851.1 ms/req)うーん、100倍は遅くありませんが、静的ファイルの場合と比較すると25倍ぐらい遅いですね。これをベースに、どれぐらい高速化できるか検討します。
まずは実行環境です。実は上記todoリストはdevelopment環境で稼働していました。これをproduction環境に変更します。production環境の方が速い。らしいです。変更の仕方は、
- config/database.ymlでproduction環境にもデータベースの設定を書く。
- config/environment.rb で「ENV['RAILS_ENV'] ||= 'production'」の行のコメントを外す。
Request rate: 0.6 req/s (1675.0 ms/req)ビミョーに速くなりました!
さらに、今回の例はセッションを使っていないので、セッションを無効にしてみます。無効にする方法はapp/controllers/application.rbを下記のように変更します。
class ApplicationController < ActionController::Base # Pick a unique cookie name to distinguish our session data from others' # session :session_key => '_Todo_session_id' session :disabled => true endこのときの速度は下記の通り。
Request rate: 0.6 req/s (1752.7 ms/req)うーん、あまりはやくならない。ていうかむしろすこし遅くなったような。セッションはDBに保存するので、DBが遅い場合はセッションを無効にすると劇的に改善することがあるようです。しかし、さくらのようにデータベースがMySQLで別のサーバになっている場合は効果があまりない。残念。
気を取り直して今回の最後の手段。必要のないモジュールをロードしないようにします。具体的には、config/environment.rbの下記の行のコメントアウトをとります(行頭の#を削除して行を有効にします)。
# Skip frameworks you're not going to use (only works if using vendor/rails) config.frameworks -= [ :action_web_service, :action_mailer ]このときの速度は下記の通り。
Request rate: 0.9 req/s (1103.7 ms/req)おおっ、だいぶはやくなった! 静的ファイルと比較して25倍から13倍によくなりました! というわけでみなさんもお試しあれ。焼石に水という気もしますが...
参考文献
- Movable Type 3.34 アップグレード, blog kazuking, 2007
- 優しいRailsの育て方, 2006
- Welcome to the httperf homepage, HP Labs, 2005