引用元:
http://gihyo.jp/dev/feature/01/rails2/0004
Rails Web アプリケーションをもっと速く
こんなストーリーを考えてみます。
あなたは, Railsを学び, アプリケーションを作成し, サービスをインターネットに公開しました。しばらくすると, 最初のユーザができます。あなたはとてもハッピーです。そうするうちにユーザが二人増え, 十人になり, 百人になりました。あなたはハッピーです, ユーザーもみんなハッピーです。
でも, ユーザが千人になり, 一万人になり…。といった場合, 何が起こるでしょうか?
そこで起こるのはアプリケーションへの同時接続数増加によるサービス提供速度の低下です。ユーザ数が一万人を越えてしまうWebサーバに特有の問題は, C10K問題として知られています。
それでなくとも, 残念ながらRailsは同様他種フレームワークと比べて, 単位時間あたりの処理量が低いことで知られています。その理由は, RailsではRubyが遅くて, NativeThreadに対応できず, ERbが遅くて, Helperが遅くて, Routingが遅い。とさまざまです。
ユーザー数の増加が現在のアーキテクチャの許容以上の負荷になってしまった場合, 考えられる抜本的な対策として,
- 別の言語で書き直す
(PythonやPerlやPHPやC++) - インフラを外部にまかせてしまう
(Google App Engine, Amazon EC2, Microsoft Live Mesh)
といったものがあります。
まず最初の, 別の言語で書き直す。これもよくある決断です。アーロン・ シュワルツ(Aaron Swartz)はredditをCommon LispからPhytonに書き直しました。また、TwitterがRuby On RailsからPHPやJavaに乗り換えるという噂は事あるごとに流布されます。
次の, 「インフラをGoogle App Engine等のCloud Computerにまかせてしまう」 というのは今後のトレンドになりそうです。ただし, Cloud Computerの利用が一般化した場合, 現在のWeb技術者が持っている, サーバ側のDB, ネットワーク, IOのチューニングの知識のいくらかは陳腐化してしまうでしょう。
ここではそういった決断をふみとどまって, 現状の環境でもうちょっとがんばってみよう, という場合の, Railsアプリケーションのパフォーマンス測定・ 改善法について考えていきたいと思います。
Measure before optimizing~Railsを計測しよう
Railsアプリケーションが遅い! からといって, 闇雲に最適化を開始するのはあまりおすすめできません。アプリケーションの最適化に入る前に, さまざまな視点から"計測"が必要になります。
Rubyコードの計測:ruby-prof
当然ながらRailsアプリケーションは, Rubyで出来ています。Rubyの性能を測定するための事実上標準のprofilerがruby-profです。
それでは, ruby-profの使用法について解説したいと思います。
ruby-profileはgemパッケージとして提供されています。まずはgemコマンドでインストールを行います。
gemコマンド
# gem install ruby-prof
次に, インストールされたパッケージの, ruby-prof/ rails_ plugin/ ruby-profを, Railsアプリケーションフォルダのvendors/ pluginsにコピーし, pluginとしてインストールします。
ruby-profプラグインをインストール
% cd minicious % cp -R /usr/lib/ruby/gems/1.8/gems/ruby-prof-0.6.0/rails_plugin/ruby-prof vendor/plugins
次に, コピーしたruby-prof/ lib/ profiling. rbを以下のようにコメントアウト, コメント除去します。
vender/ plugins/ ruby-prof/ lib/ profiling. rbから抜粋
# Create a flat printer
#printer = RubyProf::FlatPrinter.new(result)
#printer.print(output, {:min_percent => 1,
# :print_file => false})
#logger.info(output.string)
## Used for KCacheGrind visualizations
printer = RubyProf::CallTreePrinter.new(result)
path = File.join(LOG_PATH, 'callgrind.out')
File.open(path, 'w') do |file|
printer.print(file, {:min_percent => 1,
:print_file => true})
end
ここまで設定した段階で, ruby-profが有効になります。railsサーバを起動します。
% script/server
起動した, サーバに対するアクセス結果がlog/ callgrind. outとして出力されます。
出力されたcallgrindを閲覧するためのビューワがKCachegrindです。
Linux系のディストリビューションに対してはパッケージが提供されていますが, それ以外のOSについてはソースコードでの提供になります。そのためインストール手順については省略します。
KCachegrindを実行してみます。
KCachegrind 実行
% kcachegrind log/callgrind.out
以下が実行例です。
ruby-profとKCachegrindによってボトルネックが可視化されました。
Rubyのプロファイリング結果に基づく, パフォーマンス改善法については, Rubyの作者まつもとゆきひろ氏による 「まつもと直伝 プログラミングのオキテ 第18回 プログラムを高速化する (その2) 」 等が参考になります。
著者プロフィール
鎌田達哉(かまだたつや)
SI企業勤務。10年ほど前にはじめて自分で行ったプログラミングはRubyによるものであったが,語ってもにわかには信じてもらえないような紆余曲折を経て現在に至る。現在は,JVM上の言語実装に興味あり。ありがちですが,Scalaにはまり中。
バックナンバー
Rails2.0の足回りと中級者への道
- 第4回 Railsアプリケーションをもっと速く
- 第3回 Rails2.0で作るRESTfulアプリケーション(後編)
- 第2回 Rails2.0で作るRESTfulアプリケーション(前編)
- 第1回 Rails2.0の足回り
0 コメント:
コメントを投稿