Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Ruby on Railsで持続可能な開発を行うために取り組んでいること
Search
AK
March 01, 2025
Technology
3
160
Ruby on Railsで持続可能な開発を行うために取り組んでいること
TokyoWomen.rb #1の登壇資料です。
https://tokyowomenrb.connpass.com/event/342573/
AK
March 01, 2025
Tweet
Share
More Decks by AK
See All by AK
クラシルの現在とこれから
am1157154
1
1.1k
Other Decks in Technology
See All in Technology
LINE NEWSにおけるバックエンド開発
lycorptech_jp
PRO
0
310
AIエージェント開発のノウハウと課題
pharma_x_tech
7
4.1k
JavaにおけるNull非許容性
skrb
2
2.7k
マーケットプレイス版Oracle WebCenter Content For OCI
oracle4engineer
PRO
3
530
あなたが人生で成功するための5つの普遍的法則 #jawsug #jawsdays2025 / 20250301 HEROZ
yoshidashingo
2
310
JAWS FESTA 2024「バスロケ」GPS×サーバーレスの開発と運用の舞台裏/jawsfesta2024-bus-gps-serverless
ma2shita
3
270
ディスプレイ広告(Yahoo!広告・LINE広告)におけるバックエンド開発
lycorptech_jp
PRO
0
470
JAWS DAYS 2025 アーキテクチャ道場 事前説明会 / JAWS DAYS 2025 briefing document
naospon
0
2.5k
エンジニア主導の企画立案を可能にする組織とは?
recruitengineers
PRO
1
250
AWS Well-Architected Frameworkで学ぶAmazon ECSのセキュリティ対策
umekou
2
150
Amazon Aurora のバージョンアップ手法について
smt7174
2
160
ABWG2024採択者が語るエンジニアとしての自分自身の見つけ方〜発信して、つながって、世界を広げていく〜
maimyyym
1
190
Featured
See All Featured
The Illustrated Children's Guide to Kubernetes
chrisshort
48
49k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.7k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
10
520
Gamification - CAS2011
davidbonilla
80
5.2k
The Power of CSS Pseudo Elements
geoffreycrofte
75
5.5k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
100
18k
Agile that works and the tools we love
rasmusluckow
328
21k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
280
13k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
59k
A Tale of Four Properties
chriscoyier
158
23k
Fantastic passwords and where to find them - at NoRuKo
philnash
51
3k
Music & Morning Musume
bryan
46
6.4k
Transcript
Akina Matsushima 2025/03/01 TokyoWoman.rb #1 Ruby on Railsで 持続可能な開発を行うために 取り組んでいること
松嶋 瑛奈 (Matsushima Akina) dely株式会社 バックエンドエンジニア • 2019/11~: 現職にSREとして入社 •
2022/10~: バックエンドエンジニアに転向 • Ruby/Rails歴3年目 💎 • Kaigi on Rails 2024のスポンサーLTが初登 壇、 今回で2回目です! 📣 自己紹介 @25_aaa 3 @akingo55
None
None
今回のテーマは、「持続可能な開発」
持続可能な開発? 🤔
プロダクトの性質やフェーズにあわせて、 「品質」と「開発速度」のバランスを取る こと
バランスを取りやすくするためには、 どうすればいいのか?
不要な複雑さを減らし、ソフトウェアを 「単純」にすること
今日話すこと 1. デッドコードを定期的に削除している話 2. Datadog APMを用いてパフォーマンス改善している話 💡 9年目を迎えたRailsアプリケーションを運用する中で、私たちがソフト ウェアを「単純」にするために取り組んできた2つのことについて話します。
1.デッドコードの削除 🧹
消そう。以上。 実行されないコードは消すだけだ。 引用:「Tidy First? 2章 デッドコー ド」
なぜ不要なコードが蓄積されてしまうのか? • 時間を捻出できない ⏰ ◦ 普段は機能開発に追われているため、改善系のタスクに着手する時間がとれない ◦ 改善チームやPjTを立ち上げられたらいいが、そもそも人手不足 • 後回しにして忘れ去られてしまう
◦ とりあえずバックログに入れるが、優先度低くて一生やらないタスクになる ◦ そして忘却の彼方に • そういう文化がない 😢 ◦ 機能開発こそが価値を生むものだなど、運用を軽視する文化が根強いと放置されがち ◦ 誰かが声を上げない or 障害が起きて大惨事にならない限り変わらない
私たちの解決策 • 時間を捻出できない ⏰ or 後回しにして忘れ去られてしまう ◦ 機能開発が落ち着く年末に、早めにコードフリーズして時間つくる(去年は12/19) ◦
高頻度である必要はないし、年に1回程度だと調整・説得しやすい ◦ 誰でも運用を回せるように、あらかじめ削除フローは整備しておく ◦ 年1回のコードの大掃除としてイベント化する ▪ 「年末 = 大掃除」のイメージがあるので定着しやすい • そういう文化がない 😢 ◦ 一朝一夕で文化は変わらない ◦ 強い気持ちで、根気強く地道に浸透させていくしかない
どのような手段を使うか? • 動的解析ツールを使って、プロダクションコードの使用率を計測す る (ex. coverband) • 静的解析ツールを使って、ソースコードから使われていないメソッ ドやクラスを抽出する(ex. debride)
• プロダクション環境のアクセスログからAPI単位で不要なコードを抽 出する
どのような手段を使うか? • 動的解析ツールを使って、プロダクションコードの使用率を計測す る (ex. coverband) • 静的解析ツールを使って、ソースコードから使われていないメソッ ドやクラスを抽出する(ex. debride)
• 👉プロダクション環境のアクセスログからAPI単位で不要なコード を抽出する 既存のログ基盤を活用できること && 年1回の運用なので運用コストが 一番少ない方法を選択
何を消していくのか? • サポート対象外のバージョンで使われていたモバイルのAPI • 機能として既に存在しないWebのAPI • 誰も使わなくなった社内の管理サイトの機能 ◦ 1年以上アクセスがないページや使われた痕跡がない機能は基本的に削除する •
運用が既に止まっているrakeタスク • 不要なバッチ処理 ◦ 効果の薄いプッシュ通知、誰も見ていないSlack通知 etc.
削除フロー例 1. 現在使われているAPIのパスとメソッド一覧をペアにしてCSV形式で出力 a. モバイルAPIはモバイルエンジニアに依頼する b. アクセスログから抽出する 2. ActionDispatch::Routingで出力したルーティング一覧と照らし合わせ る
※削除対象のAPIを抽出するスクリプトをチームで使い回せるようにしてい るが、年1回の実施なので完全自動化まではしていない
コードの大掃除の効果 • 毎年1万弱のコードが削除されている ◦ 2024年は約9200行削除できた 🎉 ◦ 年1運用なので、負担も少なく継続しやすかった • CIの時間が短くなる
◦ CIの時間を短縮するTipsは様々あるが、コード削除だけでも1分以上短くできる • 年末早めのコードフリーズで、運用や改善タスクを実施する時間も割 けるようになった ◦ gemのバージョンアップ ◦ APIのパフォーマンス改善 ◦ 後回しにしていたアプリケーションエラーの解消等
2. パフォーマンス改善 💨
そもそも何でパフォーマンスを改善するのか? 理由は以下の3つしかないと言われている 1. 顧客体験を向上させる 2. 運用コストを減らす 3. トラフィック増加による障害を防ぐ 引用:「Ruby on
Rails パフォーマンスアポクリファ 第1章」 • 現代のWebアプリケーションは、高速であることが「当たり前」 • Googleの研究によると、検索結果の表示が100ms~400ms遅くなるだけ で0.2~0.6%の利用ユーザーが減少したと報告されている 引用:https://research.google/blog/speed-matters/
パフォーマンス改善のお作法 • 推測するな、計測せよ && まずボトルネックを解消せよ ◦ APMを導入し、トレースデータを活用すると改善が捗りやすい(Datadog, NewRelic etc.) ◦
パフォーマンスの良し悪しを判断する指標があるとベター(SLOなど) • ダッシュボードを作成し、パフォーマンスを可視化する ◦ 作っておしまいにならないことが大事!!! ◦ 弊社の場合 ▪ 週次のサーバーサイド定例でダッシュボードを眺める時間を確保 ▪ 短期と長期の観点で見て異変がないか ▪ 改善が必要と判断されたものはチーム単位で改善タスクとして積む
効果的にパフォーマンスを改善するには? 🌟 最もユーザー体験の改善に繋がるものから順番に改善していく! どんな指標をもとに判断すればいい? • 99パーセンタイル値のレイテンシが悪い順? • リクエスト数✕平均レイテンシの値が悪い順?
個人的におすすめなやり方 • レイテンシの閾値を設定し、エン ドポイントごとにこの閾値を超え た回数をカウントする • その回数が最も多いエンドポイン トから改善していく • ユーザーに負の体験を与えている
ものから効果的に改善できる 実際のDatadogのダッシュボードから抜 粋
実際の改善事例の紹介 🐶
事例①:eager_loadの罠 • ページングありで取得するレコード数も制限されている • N+1対策のためのeager loadもしていて問題なさそう ・・・? • 早いときもあるし遅いときもあるぞ
事例①:eager_loadの罠 • レシピに紐づくユーザーのレーティングに関するレコードが膨大 になっていた • 人気なレシピの場合、レーティングが数万件ついてることも ・・・ 👈 犯人!
事例①:eager_loadの罠 • SQL実行時に ActiveSupport::Notifications経由で instantiation.active_recordイベントを取 得しているので、トレースデータのスパンタグ にセットされる • SQLの実行には取得レコード数が増えても 0.1s以下だが、ActiveRecordはインスタン
ス化するのに時間がかかってしまう
事例①:改善方法 UserRatingはリアルタイムに取得する必要はないので、recipesテーブル にuser_rating_countカラムを追加、バッチ処理で更新するスタイルに変 更 • その結果、P99の値が平均して1/10まで減少した 👏 • includesメソッドは便利で容易に使いがちだが、取得されるレコー ド数も考慮にいれないとパフォーマンスに影響する
✏
事例②: IN演算子の使い方には気を付けよう • あれ、謎の空白が目立つな? • トレースデータに何も表示されず、何が起きてるのか分からない • 発行されているSQLはINNER JOINしているな •
SQLも改善できそうだけど、空白の部分の時間が長すぎるぞ
事例②: IN演算子の使い方には気を付けよう ①で取得したIDを②のクエリのIN演算子に渡しているので、インスタンス化する時に オーバーヘッドが生じてそう 🤢(JOINするとトレースに表示されない ⚠) ① ② IN演算子に大量のIDが渡っ てきているこれは・・・
😇
事例②: IN演算子の使い方には気を付けよう • 初期からある内部リンク用API で、ロジックの見直しは今まで されていなかった • 記事に関連するレシピを取得し ているが、MIN_LIMITだけ決 めて、MAX値を決めてなかった
のでIN演算子に大量のIDを渡し てしまっていた • IN演算子も大量の要素を渡して しまうと、インデックスが使わ れずフルスキャンが走る可能性 があるので注意!
事例②: 改善方法 IN演算子に渡すID数に制限を設け、オーバーヘッドをなくす 全体で見ると1/10、クエリの速度は1/20まで改善 🎉 ① ②
事例③:効果的なインデックス貼れてないかも・・・ • 複数のテーブルをINNER JOINいるが、最適なインデックスが存在していな いことで、非常に遅いクエリが実行されていた 😇
事例③:効果的なインデックス貼れてないかも・・・ • explainで実行計画見ると、一番 カーディナリティの低いインデック スが使用されていた • そのインデックスは消去法で選択さ れており、他に使われている箇所は なく、有用なインデックスではな かった
• sys.schema_index_statisticsで インデックス使用率見れるよ (MySQL)
事例③:改善方法 • 不要なインデックスは削除し、WHERE句で指定されているカラムで複合インデッ クスを貼ることで改善した(2.61s → 347ms) • 複合インデックスは左から順に使われるので、WHERE句に指定する順番には注意 ⚠(leftmost prefixルール)
• Railsだとscope使うときにインデックスがどう貼られているか気をつけると
改善結果 • 他にもエンドポイントごとに様々な改善を実施した ◦ APIのレスポンスデータは余分なものを減らし、必要最低限なものだけ 返すようにしたり ◦ 過剰に発行されているクエリを削減したり ◦ 過度なDRYによって、非効率なクエリが発行されているコードを最適
化したり etc. • 最終的に、全体のP99.9の値が800-900msから300ms台まで減らせた 🎉
まとめ • プロダクトの品質と開発速度のバランスを取ることは難しいですが、ソフ トウェアを単純にしていくことで、両者のバランスは実現可能 • 単純さの追求は、Railsアプリケーションを安全に楽しく開発できること にもつながるよ • そのための手段として、「デッドコードの削除」や「パフォーマンス改 善」を効果的に行うための事例を紹介しました
• 年末のコードのお掃除会、おすすめなのでぜひ! • APMはそれなりに高いけどパフォーマンス改善が捗るし、どの部分がボト ルネックになりやすいのか理解が深まるのでおすすめ!
ありがとうございました!