Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
ISUCON入門 その4(終)
Search
てとらぽ
November 07, 2024
52
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ISUCON入門 その4(終)
てとらぽ
November 07, 2024
More Decks by てとらぽ
See All by てとらぽ
ISUCON入門 その3
teppgg
0
53
ISUCON入門 その2
teppgg
0
63
ISUCON入門
teppgg
0
180
Featured
See All Featured
Documentation Writing (for coders)
carmenintech
77
5.6k
The Illustrated Children's Guide to Kubernetes
chrisshort
51
53k
Unsuck your backbone
ammeep
672
58k
The browser strikes back
jonoalderson
0
1.8k
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
68
59k
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
1.3k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
232
55k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
2
410
Fireside Chat
paigeccino
43
4.1k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
1.1k
WCS-LA-2024
lcolladotor
0
890
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
Transcript
ISUCON入門 その4(終)
目次 1. 初期状態(約650点) 2. commentテーブルにインデックスを追加する(約 7000点) 3. unicorn workerプロセスを4にする(約15,000点) 4.
静的ファイルをnginxで配信する(約17,000点) 5. アップロード画像を静的ファイル化する(約 22,000点) 6. GET / を解析する 7. postとuserをJOINして必要な行数だけ取得する(約 90,000点) 8. ベンチマーカーが使用するファイルディスクリプタ上限を増加させる 9. プリペアドステートメントを改善する(約 110,000点) 10. commentテーブルにインデックスを追加する(約 115,000点) 11. postからのN+1クエリ結果をキャッシュする(約 180,000点) 12. 適切なインデックスが使えないクエリを解決する(約 200,000点) 13. 外部コマンドの呼び出しをやめる(約 240,000点) 14. MySQLの設定を調整する(約 255,000点) 15. memcachedへのN+1を解消する(約 300,000点) 16. RubyのYJITを有効にする(約 320,000点)
15. memcachedへのN+1を解消する • get_multiを使って、一回のクエリで全部取得出来るようにする 1. 11章でMySQLへのN+1クエリを、memcachedへクエリするようにした 2. MySQLの負荷は下がったが、 memcachedにはN+1クエリが残っている 3.
memcachedの機能でN+1を本当に解消する def make_posts(results, all_comments: false) # 「postごとのコメント数」の"キーのリスト"を用意しとく count_keys = results.to_a.map{|post| "comments.#{post[:id]}.count"} # 「postごとのコメント数」の"リスト"を作成する # ※用意してた"キーのリスト"を引数にすることで、一回のクエリで全部取得する cached_counts = memcached.get_multi(count_keys)
15. memcachedへのN+1を解消する • ベンチマークの結果 ➢ スコア:225272点→268771点 isucon@ip-172-31-42-22:~$ /home/isucon/private_isu.git/benchmarker/bin/benchmarker -u /home/isucon/private_isu.git/benchmarker/userdata
-t http://13.231.229.107 { "pass":true, "score":268771, "success":257043, "fail":0, "messages":[] } isucon@ip-172-31-42-22:~$
目次 1. 初期状態(約650点) 2. commentテーブルにインデックスを追加する(約 7000点) 3. unicorn workerプロセスを4にする(約15,000点) 4.
静的ファイルをnginxで配信する(約17,000点) 5. アップロード画像を静的ファイル化する(約 22,000点) 6. GET / を解析する 7. postとuserをJOINして必要な行数だけ取得する(約 90,000点) 8. ベンチマーカーが使用するファイルディスクリプタ上限を増加させる 9. プリペアドステートメントを改善する(約 110,000点) 10. commentテーブルにインデックスを追加する(約 115,000点) 11. postからのN+1クエリ結果をキャッシュする(約 180,000点) 12. 適切なインデックスが使えないクエリを解決する(約 200,000点) 13. 外部コマンドの呼び出しをやめる(約 240,000点) 14. MySQLの設定を調整する(約 255,000点) 15. memcachedへのN+1を解消する(約300,000点) 16. RubyのYJITを有効にする(約 320,000点)
16. RubyのYJITを有効にする • コンパイルを必要最小限だけにする方式(Just In Time)を有効にする ➢ /home/isucon/.local/ruby/bin/unicornを修正 ▪修正前 #!/usr/bin/env
ruby ▪修正後 #!/usr/bin/env -S ruby --yjit
16. RubyのYJITを有効にする • ベンチマークの結果 ➢ スコア:268771点→271327点 isucon@ip-172-31-42-22:~$ /home/isucon/private_isu.git/benchmarker/bin/benchmarker -u /home/isucon/private_isu.git/benchmarker/userdata
-t http://13.231.229.107 { "pass":true, "score":271327, "success":259650, "fail":0, "messages":[] } isucon@ip-172-31-42-22:~$
目次 1. 初期状態(約650点) 2. commentテーブルにインデックスを追加する(約 7000点) 3. unicorn workerプロセスを4にする(約15,000点) 4.
静的ファイルをnginxで配信する(約17,000点) 5. アップロード画像を静的ファイル化する(約 22,000点) 6. GET / を解析する 7. postとuserをJOINして必要な行数だけ取得する(約 90,000点) 8. ベンチマーカーが使用するファイルディスクリプタ上限を増加させる 9. プリペアドステートメントを改善する(約 110,000点) 10. commentテーブルにインデックスを追加する(約 115,000点) 11. postからのN+1クエリ結果をキャッシュする(約 180,000点) 12. 適切なインデックスが使えないクエリを解決する(約 200,000点) 13. 外部コマンドの呼び出しをやめる(約 240,000点) 14. MySQLの設定を調整する(約 255,000点) 15. memcachedへのN+1を解消する(約300,000点) 16. RubyのYJITを有効にする(約 320,000点)
8. ベンチマーカーが使用する ファイルディスクリプタ上限を増加させる • スキップしていた8章をやる ➢ 下記シナリオで10万点超えたあたりにエラーが出る想定だったが、 最後まで出なかったので、最後にやる 1. アプリサーバが早くなる
2. ベンチサーバからのリクエストが増える 3. 一度に開けるファイル数上限に引っかかる 4. エラー(GET ~中略~ socket: too many open files)が出る ➢ 結局、エラーをトリガーでやれてないので再現性無い ...
#<domain> <type> <item> <value> isucon hard nofile 10000 isucon soft
nofile 10000 #* soft core 0 #root hard core 100000 #* hard rss 10000 8. ベンチマーカーが使用する ファイルディスクリプタ上限を増加させる • isuconユーザのファイルディスクリプタ上限を10000にする ➢ /etc/security/limits.confに2行追記
• 設定を反映させる ➢ ログインしなおす isucon@main:~$ ulimit -n 1024 isucon@main:~$ isucon@main:~$
isucon@main:~$ exit logout There are stopped jobs. isucon@main:~$ sudo su - isucon isucon@main:~$ isucon@main:~$ ulimit -n 10000 isucon@main:~$ 8. ベンチマーカーが使用する ファイルディスクリプタ上限を増加させる
• ベンチマークの結果 ➢ スコア:271327点→272127点 isucon@ip-172-31-42-22:~$ /home/isucon/private_isu.git/benchmarker/bin/benchmarker -u /home/isucon/private_isu.git/benchmarker/userdata -t http://13.231.229.107
{ "pass":true, "score":272127, "success":260615, "fail":0, "messages":[] } 8. ベンチマーカーが使用する ファイルディスクリプタ上限を増加させる
Appendix • 前回(ISUCON入門 その3)で壊れたアプリサーバ直した ➢ 原因:imageファイルが呼ばれた際の参照先フォルダが消えていた ➢ 復旧方法: $ mkdir
/home/isucon/private_isu/webapp/public ➢ 所感:gitをガチャガチャしたときに消えたと思われる 怪しいcommit
Appendix その2 • ISUCON本一旦終えたので、雰囲気で理解する用の目次を作った 1. 初期状態(約650点) 2. DBにページ番号(インデックス)が振られてないので振る(約7000点) 3. CPU1個しか使えてないので2個使う(約15,000点)
4. 画像が呼ばれたらアプリサーバ(Ruby)を通らず、WEBサーバ(nginx)から直で配信する(約17,000点) 5. 画像を毎回バイナリから書き出してるので、pngとかで保存して、次から呼ばれたらpngを返す(約22,000点) 6. HTTP GETリクエストのログを見て、時間がかかってるDB問い合わせを探す 7. 2つのDBに1回ずつ計2回問い合わせしてる(N+1)ので、DBを合体して1回の問い合わせで済ませる(約90,000点) 8. ファイルを開ける上限が1024件になってるので、10000件開けるようにする 9. 問い合わせの種類が多くて、問い合わせテンプレ化機能自体に時間がかかってるので無効にする(約110,000点) 10. DBにインデックスが振られてないので振る(新しく発見したので再度)(約115,000点) 11. MySQLへの二重な問い合わせ(N+1)をキャッシュから返すようにする(約180,000点) 12. MySQLが遅いインデックスを自動選択してるので、早いインデックスを手動で指定する(約200,000点) 13. 暗号化処理を外部アプリから使うと遅いので、ライブラリから使うようにする(約240,000点) 14. 解析用に全出力にしてたMySQLのログ、もう要らないので無効にする(約255,000点) 15. キャッシュへの二重な問い合わせ(N+1)を一回で済ませる(約300,000点) 16. Rubyコードを全部コンパイルする方式になってるので、必要分だけコンパイルする方式にする(約320,000点)
Appendix その2 • 正しい目次(比較用) 1. 初期状態(約650点) 2. commentテーブルにインデックスを追加する(約7000点) 3. unicorn
workerプロセスを4にする(約15,000点) 4. 静的ファイルをnginxで配信する(約17,000点) 5. アップロード画像を静的ファイル化する(約22,000点) 6. GET / を解析する 7. postとuserをJOINして必要な行数だけ取得する(約90,000点) 8. ベンチマーカーが使用するファイルディスクリプタ上限を増加させる 9. プリペアドステートメントを改善する(約110,000点) 10. commentテーブルにインデックスを追加する(約115,000点) 11. postからのN+1クエリ結果をキャッシュする(約180,000点) 12. 適切なインデックスが使えないクエリを解決する(約200,000点) 13. 外部コマンドの呼び出しをやめる(約240,000点) 14. MySQLの設定を調整する(約255,000点) 15. memcachedへのN+1を解消する(約300,000点) 16. RubyのYJITを有効にする(約320,000点)