このブログははてなブログからの移行記事です。
ISUCON7に参加しました
今年は前職の先輩と現職の先輩と組んで参加しました。
結果
予選突破の20万台には遠く及ばず…
点数のブレが大きすぎてどの対策が効いたか全然わからなかったけど時系列でやったこととかやりたかったけど諦めたことをメモる。
タイムライン
私の担当はアプリケーションだった。
- INDEX追加
(user.name)
(message.id, message.channel_id)
(haveread.user_id, haveread.channel_id)
SELECT *
の撲滅get_channel_list_info
の置き換え- 最終的に一箇所しか残らなかった
- DBアクセスする前に結果返せるところは返す
- DBアクセスした後にリクエストパラメータの有無チェックしてるようなロジックがちょいちょいあった
COUNT(*)
をCOUNT(1)
に- チャンネルごとのメッセージ数カウントを専用テーブル用意して置き換え
- 毎回
COUNT
せずにSELECT
するだけでよくなった - 最初の段階で2番めに遅いクエリだったので手をつけた
- 毎回
- php-fpmのチューニング
- 使わないPHP extensionの削除
xdebug.so
, お前のことやで
N+1
をいくつか潰す
他のお二人には
とか諸々やってもらった。感謝…
やりたかったけどできなかった
/register
,/login
ページを静的コンテンツに- ロジック見ると分かるけどこの2つはPHPに捌かせる必要がない
- HTMLの配置は一瞬だったけど優先度低かったので後回しにしたのと、nginxの設定でハマってやれなかった
- キャッシュミドルウェアの追加
- ログイン判定の度に
select * from user
してるのとか - 今回は削除更新が無かったので整合性の担保も難しくなかったはず…
- ログイン判定の度に
- メッセージ取得ロジック改善
- 未読数カウントロジック修正
- こっちもメッセージ数と同じようにカウントテーブル用意しようと思ったけど初期レコードが100*1100になってしまうこと、add_messageされると1100レコードにupdateが走るので諦めた
- スギャブロエックスチームのsugyanさんが別アプローチで解決してて本当に心の底から悔しい気持ち…
- 既読数をカウントして総コメント数 - 既読数すれば未読数になる
- これなら初期レコードいらない
LIMIT
,OFFSET
殺す- php-fpmのさらなる調整
- 時間無くてかなり雑に調整した
- PHPとMySQLのコネクション最適化
他にも色々アイディアはあって
- DBサーバにもアプリを立てる
- キャッシュ用サーバとアプリを分ける
なんて案もあったけどとにもかくにもボトルネックが/icons
から他に移らなくて死んだ。
所感
とにもかくにも/icons
のリクエストを捌けて無くてしんどかった。
一番最初はDBが完全にサチっててその壁は一瞬で越えられたけどその後すぐに画像が死んでることが分かってなるほどという感じだった。
画像の脱DB化をしてもそこまでスループットが上がらず、なかなか苦しかった。
今回はそこを抜けたチームが10万の壁を越えていったのではという推測。
スギャブロエックスチームと同じ会場で解いてたので効いたところCache-Control
ヘッダあたりをいじって2回目以降リクエストさせないようにしてたらしい。ぐぬぬ…
一昨年、昨年参加して今年3回目だけど計測してボトルネック特定して確実に芽をつぶしていく力はついていると感じてて、それゆえに結構悔しい。
あとはぱっと直したコードにバグがあることが多くて結構時間を取られた。
今回はほぼ何も準備できなかったけど来年は手元で簡単にアプリが動かせるような環境を作る秘伝のタレを用意してそこでデバッグしたい。
とにかくですね
来年こそ100万円使って温泉行きたいです。