Kaigi on Rails 2021 で登壇しました
先日Kaigi on Rails 2021で、Cache on Railsというテーマで登壇しました。
参加者としての感想は雑に日記に書きましたので、この記事では登壇者としての感想を書きます。
各種資料
スライド
スピーカーノートを開くと(ほぼ完全な)トークスクリプトもついています。
Proposal
Proposal自体の他に、調査メモなども雑に置いてあります。
話した内容について
タイトル通り、Railsにおけるキャッシュについてお話しました。 話した内容の補足をします。
Avoid Using Cache
特にお伝えしたかったのは、「キャッシュを使う必要がなければ、キャッシュを使わない」ということです。
twitter.com一番話したかったことは、キャッシュを使わずになんとかなるときにキャッシュを使ってしまうのは避けよう、ということでした #kaigionrails
— 🎹 (@p_ck_) 2021年10月23日
デカデカと"Avoid Using Cache"と書かれたスライドを出すのはインパクト狙いもありつつ、しかしキャッシュが難しい技術であることを伝えられたかなと思っています。
「キャッシュ難しいよね」「キャッシュを使うなって言っていたの良かった」といったフィードバックを頂いているので、これに触れて良かったなと自分でも思っています。
とはいえキャッシュはパフォーマンス改善の強力な武器であることには変わりありません。ということで、Railsで使える色々なキャッシュについてお話しました。
Active Record SQL Cache
Active Record SQL Cacheは、1回のリクエストで複数の同じSQLが発行されたらそれをキャッシュする機能です。
SQL Cache では、オブジェクトのallocationは減らないという点について特にお伝えしたかったです。 実際の開発でもSQL Cacheには乗っているもののオブジェクトのallocationは削減されておらず、パフォーマンスに影響が出ていることがありました。そのため、この問題を意識しているとパフォーマンスの改善に役立つことがあると思います。
Rails.cache
Rails.cache
はLow-LevelなキャッシュのAPIです。Rails.cache.fetch {}
が便利ですね。
ここで特にお伝えしたかったのは、キャッシュキーの計算の方法についてです。
Active RecordのモデルのオブジェクトやRelationのオブジェクトはcache_key
メソッドなどを定義しています。
そのためRails.cache.fetch(User.first) {}
やRails.cache.fetch(User.all) {}
のように、これらのオブジェクトを直接キャッシュのキーとして渡せます。
これは中々便利な反面、Relationの場合はキャッシュキーを計算するためにSQLクエリが実行されます。
また、キャッシュキーのバージョニングもなかなか面白い最適化だなと思ったので紹介しました。 もし興味があればこの効果について解説しているブログ記事があるので、ぜひ読んでみてください。 ref: https://www.bigbinary.com/blog/rails-adds-support-for-recyclable-cache-keys
ETag
ETagは、ざっくり言ってしまえばURL単位のキャッシュキーです。
ここでは、Rack::ETag
ミドルウェアとActionController::ConditionalGet
の2つの方法について紹介しました。
Rack::ETag
はRailsデフォルトで用意されていて特に意識せず使える反面、CSRFトークンが原因してあまり意味がないケースが多いことを説明しました。
ActionController::ConditionalGet
はより細やかなコントロールができるため、パフォーマンス改善の効果はより大きなものが期待できます。
一方でETagの計算は自分でやる必要があるため、正しいETagを設定しなければキャッシュが適切に更新されない可能性も生まれてしまいます。
ETagの有効活用は自分ではまだまだ知見が少ないので薄い紹介になりましたが、これを見て活用をしていただけたら嬉しいです。
Browser CacheStorage
最後の項目として、ブラウザのCacheStorage APIの紹介をしました。
このAPIは実際に私も活用していますが、発表でも話したとおりプリミティブなAPIであるため、キャッシュの有効期限の管理などをしたい場合には自分で実装する必要があります。
なおスライドではGitのコミットのSHA1を使ってキャッシュの破棄を実装していますが、これと類似の方法はMDNのサンプルにも書かれています。 ref: https://developer.mozilla.org/ja/docs/Web/API/Cache#examples
話さなかったこと
"Out of scope"のスライドでも話したとおり、このトークでは色々なことを話しませんでした。
話さなかったことの中でも特にCDNについては期待していた方も多かったかもしれません。 今回はRails開発者がRailsのコードを書いていて出会うことが多いであろうキャッシュを中心に紹介したので、CDNなどについてはスコープから外れていました。
……というのは半分言い訳で、CDNを始めとして話さなかったことの大半について自分が詳しくないというのも大きな理由です。 これは自分の力不足であるため、いつか人前で話せるぐらいには実力がついたら良いなと思っています。
また、話さなかったことも重要なトピックであることには変わりありません。興味があれば調べてみても良いでしょう。 (いや、page cachingとかは私はいいかな……って感じですが……)
録画について
今回の発表は事前に録画を行いました。
録画にはOBSを使いました。凝った編集などはできる気がしないので、何回か練習した上での一発撮りです。
RubyKaigiのときにも思いましたが、録画をしていると当日が比較的平静でいられるのは良いですね。 一方録画締切から本番まで1ヶ月ほどあるので、Kaigi on Rails直前などは少し気持ちが冷めたりもしていました。とはいえ本番にはかなり暖まった気持ちで臨めたのであまり問題はありませんでした。
少々トラブルがあって私の顔をお届けできなかったのは残念です。(OBSのプラグインがいい感じに動かなかった…)
当日に関して
録画での発表ということで、当日はYouTubeのチャットやTwitterのコメントを見つつ、適宜自分もコメントをしたりしていました。 YouTubeのプロフィールを設定するのが面倒で本名+実写アイコンでの対応になりました。「なんか我が物顔で解説しているけど、誰?」となっていそうだったのはちょっとした反省点ではあります。
一応発表中にreBakoの方にもいたのですが、こちらは誰も来ませんでした。発表を見つつ登壇者とガヤガヤするというのは難しいのかもしれないですね。
スライド全体を通して
参考にした記事や、実装があるソースコードへのリンクをなるべくスライドに埋め込むことを意識しました。 これは、私の発表内容をより深く知りたくなった方が、各トピックについて調べるための手がかりになるでしょう。
発表冒頭でもこのトークのゴールの1つとして「Railsでキャッシュを使う際のリファレンスとしてこのスライドを使えること」を挙げました。 このスライドだけでキャッシュを完璧に使いこなせるかと言うと無理だと思いますが、とはいえ何かあった時にまた見に来るぐらいの情報はあるんじゃないかなと思っています。
最後に、このような素晴らしい場を提供していただいたKaigi on Railsの運営の皆様、ありがとうございました。 オンラインカンファレンスとして、とても良い体験だったと思います。