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のWebアプリケーションを50倍速くする方法 / How to Make a Ruby...
Search
hogelog
November 14, 2024
Technology
1.3k
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
RubyのWebアプリケーションを50倍速くする方法 / How to Make a Ruby Web Application 50 Times Faster
hogelog
November 14, 2024
More Decks by hogelog
See All by hogelog
スマホでゲームをするか、漫画を読むか、開発をするか / Gaming, Reading or Coding on my phone.
hogelog
1
130
dentaku - Ruby製の電卓CLI / dentaku - A Ruby CLI Calculator
hogelog
0
55
"複雑なデータ処理 × 静的サイト" を両立させる、楽をするRails運用 / A low-effort Rails workflow that combines “Complex Data Processing × Static Sites”
hogelog
3
6.2k
Javaアプリケーションの配布とパッケージング / Distribution and packaging of Java applications
hogelog
4
990
なぜ Rack を理解すべきかプレトーク / Why should you understand Rack - Pre-talk
hogelog
0
450
ruby/irbへのコントリビュートと愉快な仲間たち / RubyKaigi 2024 Wrap Party
hogelog
0
250
RubyKaigi 2024 LT: Visualize the internal state of ruby processes in Real-Time
hogelog
0
330
Talk about CI and testing of the STORES
hogelog
2
630
小3の子がいるエンジニアの昔と今。
hogelog
0
1.7k
Other Decks in Technology
See All in Technology
スタートアップにAmazon EKSは早すぎる? マルチプロダクト戦略を加速する Platform Engineeringの実践 / Is Amazon EKS Too Soon for Startups? Practical Platform Engineering to Accelerate a Multi-Product Strategy
elmodev09
1
2k
知見・人・API・DB・予算 ─ ナイナイ尽くしだった人事データ整備 with dbt、5年間の学び
ken6377
1
110
FinOps X 2026 Recap from Engineer Side #JapanFinOps
chacco38
0
200
5分でわかる Amazon Connect_20260608
hwangbyeonghun
0
150
PostgreSQL 19 新機能概要 OSC Hokkaido 2026
nori_shinoda
0
260
「ビジネスがわかるエンジニア」とは何か?
ryooob
0
430
AWS Summit の片隅で、体育座りしながらコミュニティがにぎわう理由を考えた
k_adachi_01
2
310
きのこカンファレンス2026_肩書きを外したとき私は誰か
yamasatimi
1
110
40代で“やっとエンジニアになれた”――閉じた学びを開き、空の青さを知る / 20260628 Naoki Takahashi
shift_evolve
PRO
4
1.4k
起点・思考・出力で分解する 〜PM業務の自動化設計〜
kazu_kichi_67
2
1.2k
【FinOps】データドリブンな意思決定を目指して
z63d
3
540
GitHub Copilot運用のリアル ~AI Credit時代にどう向き合うか~
takafumisu2uk1
0
570
Featured
See All Featured
Ruling the World: When Life Gets Gamed
codingconduct
0
270
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
370
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
160
Done Done
chrislema
186
16k
Tell your own story through comics
letsgokoyo
1
980
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
170
Technical Leadership for Architectural Decision Making
baasie
3
430
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
Utilizing Notion as your number one productivity tool
mfonobong
4
330
The Curse of the Amulet
leimatthew05
2
13k
Git: the NoSQL Database
bkeepers
PRO
432
67k
How to Think Like a Performance Engineer
csswizardry
28
2.7k
Transcript
@hogelog 2024-11-14 STORES.rb Railsのはなし RubyのWebアプリケーションを50倍速くする方法
なまえなど 2 - @hogelog (GitHub, Twitter X, 社, …) -
小室 直 (Komuro Sunao) - STORES 株式会社 ソフトウェアエンジニア
今日する話 3 - Ruby製Webアプリケーションを高速化します - 1 processでの処理性能を計測 - ローカル環境 (Apple
M1 Max) で検証 - 一部実装はGitHubにpush済 https://github.com/hogelog/example-storesrb-ruby-webapp-tuning - 対象は最近ホットなCSP (Content Security Policy) レポートを 受け取るだけのWebアプリケーション
Content Security Policy (CSP) とは 4 - Content-Security-Policyヘッダを付与することで ブラウザが読み込むリソースを制限できる機能 -
XSS攻撃の軽減とレポーティングなどが可能 - レポートをHTTP経由で受け取り - 詳しくは https://developer.mozilla.org/docs/Web/HTTP/CSP
対象Webアプリケーションの仕様 5 - CSPレポート (application/csp-report) を受け取って 標準出力に表示 - その後集計してレポーティングする想定 -
エンドポイントは POST /reports
1. モノリシックRailsアプリケーションに実装
モノリシックRailsアプリケーションに実装 7 - CSPを設定するネットショップモノリシックRailsに レポート用エンドポイントを組み込み class ReportsController < ApplicationController skip_before_action
:verify_authenticity_token def create payload = JSON.parse(request.body.read) message = { time: Time.zone.now. to_s, report: payload[ "csp-report" ], } $stdout .puts JSON.generate(message) head :created end end
モノリシックRailsアプリケーション実装のベンチマーク結果 8 - 289.47 requests/sec - はたして50倍速くすることはできるのか $ wrk -t5
-d10s -s wrk.lua http://localhost:3000 Running 10s test @ http://localhost:3000 5 threads and 10 connections Thread Stats Avg Stdev Max +/- Stdev Latency 34.22ms 6.76ms 72.72ms 67.41% Req/Sec 58.00 13.03 101.00 68.40% 2914 requests in 10.07s, 10.41MB read Non-2xx or 3xx responses: 2914 Requests/sec: 289.47 Transfer/sec: 1.03MB
2. 新規Railsアプリケーション
新規Railsアプリケーションで実装 10 - ` rails new csp-report-collector --api --minimal --skip-test
--skip-active-record ` - POST /reports 実装は同様なので省略 - 5550.35 requests/sec -> 19倍 $ wrk -t5 -d10s -s wrk.lua http://localhost:3000 Running 10s test @ http://localhost:3000 5 threads and 10 connections Thread Stats Avg Stdev Max +/- Stdev Latency 8.97ms 11.95ms 56.79ms 79.94% Req/Sec 1.12k 232.43 1.73k 67.80% 55754 requests in 10.05s, 21.52MB read Requests/sec: 5550.35 Transfer/sec: 2.14MB
新規Railsアプリケーションの改善ポイント 11 - モノリシックRailsアプリケーション - POST /reports には不要な大量のライブラリ - 様々なコールバック、Rackミドルウェアなど
- Pitchfork (1processの同時処理は1リクエスト) - 新規Railsアプリケーション - APIモードの最小限のRailsのみ利用 - Puma (1 process, 3 threads)
3. 新規Railsアプリケーションのチューニング
新規Railsアプリケーションをチューニング 13 - Rackミドルウェアを可能な限り削除 (ActionDispatch::HostAuthorization, Rack::Sendfile, ActionDispatch::Static, ActionDispatch::ServerTiming, Rails::Rack::Logger, ActionDispatch::RequestId,
ActionDispatch::RemoteIp, ActionDispatch::ShowExceptions, ActionDispatch::DebugExceptions, ActionDispatch::ActionableExceptions, ActionDispatch::Reloader, ActionDispatch::Callbacks, Rack::ETag, Rack::Head, Rack::Runtime, Rack::ConditionalGet, ActionDispatch::Executor ) - Puma: 1 process, 2 threadsに調整 - 11071.26 requests/sec -> 38倍 $ wrk -t5 -d10s -s wrk.lua http://localhost:3000 Running 10s test @ http://localhost:3000 5 threads and 10 connections Thread Stats Avg Stdev Max +/- Stdev Latency 14.11ms 18.67ms 62.85ms 78.87% Req/Sec 2.23k 622.10 3.08k 46.40% 111464 requests in 10.07s, 32.56MB read Requests/sec: 11071.26 Transfer/sec: 3.23MB
新規Railsアプリケーションのチューニングポイント 14 - 処理を限りなく薄くするためRackミドルウェアを削除 - active_model/railtie, action_view/railtie も - アプリケーション傾向からスレッド数を調整
(3 -> 2) - スレッド数についてはKaigi on Rails 2024 “都市伝説 バスターズ「WebアプリのボトルネックはDBだから言 語の性能は関係ない」” がわかりやすいです
4. Railsをやめてみる
RailsをやめてRackアプリとして実装 16 - Rackアプリケーションとして POST /reportsを実装 require "json" class App
def call(env) if env["REQUEST_METHOD" ] == "POST" && env["PATH_INFO"] == "/reports" return handle_report(env[ "rack.input" ]) end [404, {}, [ ""]] end def handle_report (body) payload = JSON.parse(body.read) message = { time: Time.now. to_s, report: payload[ "csp-report" ], } $stdout .puts JSON.generate(message) [201, {"content-type" => "application/csp-report" }, [""]] end end
Rackアプリケーションのベンチマーク結果 17 - Puma: 1 process, 2 threads - 24257.29
requests/sec -> 84倍 🎉 $ wrk -t5 -d10s -s wrk.lua http://localhost:3000 Running 10s test @ http://localhost:3000 5 threads and 10 connections Thread Stats Avg Stdev Max +/- Stdev Latency 13.71ms 18.33ms 68.44ms 78.95% Req/Sec 4.88k 1.32k 6.68k 49.00% 244153 requests in 10.07s, 18.89MB read Requests/sec: 24257.29 Transfer/sec: 1.88MB
Rackアプリケーションの改善ポイント 18 - Puma, Rackアプリケーションという最小限のコードしか 動いていない - YJIT、GC調整などで更に高速化は目指せるかもしれない
ふりかえり 19 - 歴史を捨て、Railsを捨てることでWebアプリケーショ ンを50 84倍高速化することは可能🎉 - 歴史が詰まったモノリシックRailsアプリケーショ ンには色々なロジックが詰まっている -
Railsにも色々詰まっている - Q. 本当にRack版アプリケーションを運用する? - A. 現実的な選択肢にあげても良いなと思う
検証しててわかった嬉しいこと: json gemの高速化 20 - json 2.7.2: 23522.80 req/s -
json 2.8.1: 24257.29 req/s