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
140
dentaku - Ruby製の電卓CLI / dentaku - A Ruby CLI Calculator
hogelog
0
66
"複雑なデータ処理 × 静的サイト" を両立させる、楽をするRails運用 / A low-effort Rails workflow that combines “Complex Data Processing × Static Sites”
hogelog
3
6.6k
Javaアプリケーションの配布とパッケージング / Distribution and packaging of Java applications
hogelog
4
1k
なぜ Rack を理解すべきかプレトーク / Why should you understand Rack - Pre-talk
hogelog
0
460
ruby/irbへのコントリビュートと愉快な仲間たち / RubyKaigi 2024 Wrap Party
hogelog
0
270
RubyKaigi 2024 LT: Visualize the internal state of ruby processes in Real-Time
hogelog
0
340
Talk about CI and testing of the STORES
hogelog
2
640
小3の子がいるエンジニアの昔と今。
hogelog
0
1.8k
Other Decks in Technology
See All in Technology
サイボウズ 開発本部採用ピッチ / Cybozu Engineer Recruit
cybozuinsideout
PRO
12
85k
AI時代のデータ基盤を考える問い
pacocat
0
280
ホームラボ紹介
y_sera15
0
230
型落ちシンクライアント端末のPoEモジュールを自作したかった話
logica0419
0
380
AIのためのEthernet技術動向 (SerDes)
markunet
1
300
属人化を叩き割れ!「制作加速」と「安定化」の矛盾を打破する:8年目プロダクトが辿り着いた「ミスが起こり得ない」アセット制作フローの全貌
gree_tech
PRO
0
360
2026-08-15 JAWS-UG 茨城 #16 Secrets ManagerにおけるSecret値の管理(Terraformの場合) / Secrets Manager Secrets
masasuzu
0
560
ソフトウェアサプライチェーンの構造的リスクとコンテナ環境の保護
kyohmizu
5
890
Kiro WebとCloud Sessions
nagisa53
2
160
Kiro Crew入門 - 常駐エージェントの仕組みと使いどころ / Intro to Kiro Crew
k_adachi_01
1
840
RelayerというPHPのフレームワークを作った
polidog
PRO
0
130
Kiro入門|仕様駆動開発で変わるAI時代の開発スタイル
cmkudo
0
340
Featured
See All Featured
The World Runs on Bad Software
bkeepers
PRO
72
12k
Rails Girls Zürich Keynote
gr2m
96
14k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
900
Designing for humans not robots
tammielis
254
26k
Abbi's Birthday
coloredviolet
3
9.4k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
232
55k
Six Lessons from altMBA
skipperchong
29
4.5k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
1k
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
290
Why Our Code Smells
bkeepers
PRO
340
58k
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
3
480
WENDY [Excerpt]
tessaabrams
11
39k
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