Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Ruby on Railsで持続可能な開発を行うために取り組んでいること
Search
AK
March 01, 2025
Technology
4
360
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
クラシルの現在とこれから
25_aaa3
1
2.1k
Other Decks in Technology
See All in Technology
AI-DLCを現場にインストールしてみた:プロトタイプ開発で分かったこと・やめたこと
recruitengineers
PRO
2
200
Agent Skillsがハーネスの垣根を超える日
gotalab555
5
2.6k
コンテキスト情報を活用し個社最適化されたAI Agentを実現する4つのポイント
kworkdev
PRO
1
1.8k
2025年 開発生産「可能」性向上報告 サイロ解消からチームが能動性を獲得するまで/ 20251216 Naoki Takahashi
shift_evolve
PRO
2
210
接客歴・営業歴の方が長いエンジニアから見たre:Invent2025
yama3133
0
100
AIエージェント開発と活用を加速するワークフロー自動生成への挑戦
shibuiwilliam
4
730
Microsoft Agent 365 についてゆっくりじっくり理解する!
skmkzyk
0
430
Connection-based OAuthから学ぶOAuth for AI Agents
flatt_security
0
230
Oracle Database@Google Cloud:サービス概要のご紹介
oracle4engineer
PRO
1
730
MySQLとPostgreSQLのコレーション / Collation of MySQL and PostgreSQL
tmtms
1
1.1k
AI時代の新規LLMプロダクト開発: Findy Insightsを3ヶ月で立ち上げた舞台裏と振り返り
dakuon
0
360
AWSインフルエンサーへの道 / load of AWS Influencer
whisaiyo
0
180
Featured
See All Featured
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
0
940
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
25
Into the Great Unknown - MozCon
thekraken
40
2.2k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
3.8k
Site-Speed That Sticks
csswizardry
13
1k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
64
Done Done
chrislema
186
16k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.3k
Thoughts on Productivity
jonyablonski
73
5k
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Reality Check: Gamification 10 Years Later
codingconduct
0
1.9k
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
83
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はそれなりに高いけどパフォーマンス改善が捗るし、どの部分がボト ルネックになりやすいのか理解が深まるのでおすすめ!
ありがとうございました!