読者です 読者をやめる 読者になる 読者になる

Rails アプリケーションのパフォーマンスについて RubyKaigi 2013 で発表しました

エンジニア日記

インフラストラクチャー部の成田です。 先日開催された RubyKaigi 2013 で、 "High Performance Rails" というタイトルの発表をしてきました。

スライドと動画

発表の様子は ustream の録画をご覧ください。

[ustream id=33559705 hwaccel=1 version=3 width=480 height=302]

スライドは以下にアップロードしてあります。

High Performance Rails (long edition) // Speaker Deck

なお、発表時間の都合上、当日はここから 40 枚ほどのスライドを削除してしまいました。発表に使った短いバージョンのスライドはこちらです。

発表の概要

クックパッドは 2008 年から Ruby on Rails を採用し、ずっと使い続けてきました。サービスが成長するとともに、Rails アプリケーションのコードは日に日に巨大かつ複雑なものになってきています。

私はクックパッドのパフォーマンスを担当しており、どのようにしたら、成長を続ける Rails アプリケーションの速度を保ち続けることできるのかという課題に、日々取り組んできました。そのノウハウの一部を、今回の RubyKaigi で発表しました。

今回の発表では、以下のような内容に触れています。もし興味のあるキーワードがあれば、ぜひスライドや録画を見てみてください。

  • Rails における "レスポンスタイム" はどこの数字を見るべきか
  • Unicorn になぜ Nginx が必要なのか
  • Ruby バージョンアップによるパフォーマンスの改善
  • 誤解されがちな ActiveRecord のオーバヘッド
  • 巨大なルーティングがヘルパーメソッドを遅くする例
  • テンプレートエンジンの違いがどのようにパフォーマンスに影響するか
  • UnicornGC を切って高速化する際のノウハウ
  • Arproxy を使ったスロークエリの集計事例

なお、以下の内容は、ロングバージョンのスライドには書かれていますが、 RubyKaigi では発表しませんでした。簡単に補足しておきます。

Rails における条件付き GET リクエストの処理について

条件付き GET については語り始めるととても長くなってしまうので割愛しました。

条件付き GET リクエストをうまくコントローラの中で処理してやると、コンテンツが更新されてない場合には、ビューのレンダリングをせずに "304 Not Modified" レスポンスを返せるため、実行される Ruby コードのステップ数を大幅に減らす効果があります。

動的なウェブアプリケーションでは、使えるシーンは限られると思いますが、使えそうな箇所にはぜひ使ってみてください。 詳しくは、 RailsGuides の Caching with Rails をご参照ください。

Russian-doll Caching について

個人的にキャッシュについてはとても思い入れがあって、こちらも語り始めるととても長くなってしまうので、本番では割愛しました。

Russian-doll Caching (Cache Digests) は、Rails 4 に導入された機能です。これは、複数のフラグメントキャッシュを入れ子にしている場合に、内側のコンテンツの更新に連動して、外側のフラグメントキャッシュのキーが自動的に変更されるというものです。

詳しい挙動については、以下の RailsCasts を見れば、すぐに理解できると思います。

#387 Cache Digests - RailsCasts

また、この実装に至った背景となる思想について、 DHH によるブログ記事がありますので、興味があれば見てみてください。

How key-based cache expiration works by David of 37signals

キャッシュは、パフォーマンス改善において非常に重要な技術なので、 Rails が提供しているキャッシュ機能についてはしっかり把握しておくことをおすすめします。

おわりに

国際会議として生まれ変わった RubyKaigi 2013 は非常に素晴らしいものでした。スタッフの皆様には厚くお礼申し上げます。

クックパッドは Ruby を活用することでサービスを成長させてこられました。Rubyがあるおかげで、2000万以上の世帯の食生活がより楽しいものになっています。その感謝の気持ちを、これからも Ruby 関連イベントのスポンサーとしてや、 OSS 活動などを通して、 Ruby コミュニティに還元していきたいと考えています。

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/