このブログははてなブログからの移行記事です。
ISUCON8に出場して予選で散りました。
@kazeburoさんと@masartzさんとそたぶろるっつという名前のチームで一緒に出場しました。ありがとうございました!
結果
後半、少し追い上げるも予選突破ラインに遠く及ばず…。
fail地獄がつらかった。
やったこと
私は主にアプリケーションを見た。つらつらと。言語はNode.jsを選択しました。
- 環境整備
- lintツール導入(TypeScriptだったのでtslint入れた)
- ts-nodeでのアプリ起動をやめてcompile後のjsを実行する
- Node.jsのバージョンをv10.10.0へ変更
- サーバ構成を変更
- 無駄に
sheets
テーブルを見てるところをハードコード- 1000件程度のデータだったが
rank
とnum
カラムがわかればsheet_id
がわかるし、rank
とsheet_id
がわかればnum
がわかるデータ構造になってたのでそこを参照したりJOINしてるところをつぶした - reportのところのJOINをつぶすのだけ時間無くてできなかった
- SQL呼び出しが減るわけでなかったので後回しにしてしまった
- 1000件程度のデータだったが
getEvents
でアプリでpublic_flg
のfilterをかけてるものをflag見てSQLを変えるよう分岐- いくつかの
getEvent
呼び出し部分を単一のSQLに変更getEvent
内はいろいろやっているが読んでみるとシンプルなSELECT文で置き換えられる場所がいくつかあった
ORDER BY RAND()
をやめる- 予約されてない席でなく、予約してる席を全件取得するようにした(最大でも1000record)
SELECT sheet_id FROM reservations WHERE event_id = ? AND canceled_at IS NULL
- これだと全ランク混ざるが
rank
がわかればsheet_id
のrangeがわかるのでその範囲だけでループを回す
- 予約してる席が分かれば予約されてない席がわかるのでそこからrandomで引っ張って処理した
- 最初、randomじゃなくても行けないかなと思って試したけどだめだった
- あとから「固定シーケンシャル番号を作って擬似ランダムにする」というアイディアが出て、頭を壁に打ち付けた
- 予約されてない席でなく、予約してる席を全件取得するようにした(最大でも1000record)
その他、チームメンバーには
- INDEXの追加
getEvents
のN+1撲滅- 残り座席数のtable化
- SQL調整
- その他環境整備やアプリレイヤー以外のチューニング
をひたすらやってもらってた
反省
- 去年に引き続き凡ミスが多かった
- ローカルでアプリ環境を作るという選択をしなかったので本番デバッグすることが多く、効率が悪かった
- 他チームが「30分で作れなかったらやらない」という基準で取り組んで、作れたと言ってて時間で区切るのは賢いと思った
- TypeScript実装だったので実装が堅牢だったかというと必要最低限の型付けしかなかったので思い切って最初20分くらい、コールドリーディング&型付けに投資もありかとおもった
- 特にSQLの返り値周りはなんの値がどう加工されてるのか読み解くのに苦労した
- やろうと思ってやらなかったがInspector立ち上げてデバッグするのもありだった
- pm2立ち上げた後から設定入れるのが面倒でやらなかったがやるべきだった。判断ミス
- 後半、ほとんど何もできなかった
- 予約/キャンセルエンドポイントとずっとにらめっこしてたがどうすれば改善できるのかわからなかった
- わからないならわからないで割り切って、きな臭いSQLを丁寧にチューニングしていくとかできることはあったはず
- 正直、failの絶望感に打ちひしがれてる感が強かった(本戦出場チームもこのあたりは同じだったらしい)
- pm2の使い方はもっと調べておくべきだった
- inspector付きで立ち上げるとかloggingとか
- このあたりは仕事で触る機会もある可能性あるしISUCON問題の復習で丁寧に触っておく
まとめ
仮にもハイトラフィックなアプリのBackendを1年半やっての敗北なので強い気持ちで1年間修行します。
来年のISUCON予選突破するまでビール禁止します
— きりん (@sota1235) September 16, 2018