ISUCON6にmorimoto組で参加してきました
ISUCON6に参加しました
ISUCON6 、日曜日に参加しました。前々から出てみたいなーと思ってはいたものの、面子をゆるぼしてみたものの集まらず…と見送りかなーと思っていたところ、社内メンバーで組めることになって自分でも驚きの布陣で参戦することに。ありがとうございました!
足回りや方針はfujiwaraさんに引っ張っていただきつつ、残る2名で実装がんばるぞい、という感じで挑みました。実装言語はPerlでやりました。
事前準備
当日タイムライン
当日のスコア遷移をメモしてなかったので朧げですが、slackとgithubのログを掘り返しつつ、こんなことをしましたメモです。アプリ側しかみてないので覚えていることをさらっと。
9:00
- 集合&作業場設営
全員起床成功。
会議室を確保してなかなかよい環境でできました。
こんな感じで頑張ります #isucon pic.twitter.com/VF2Z99wZWH
— もし (@moshisora990) 2016年9月18日
10:00〜11:00
- Azureにdeploy、chefを回して環境準備。30分くらいかかった。
- dumpとかbackupとかしておく。
- (たぶん)ミドルウェア類設定を反映。
- アプリケーションをさわってなんとなく把握。
11:00〜12:00
- ログとか計測とか。
- コード読む。
- isutarをisudaに統合。
- ローカルで動かないと辛いですねーと環境を作り始める。
12:00〜15:00
スコア伸びるまで結構つらい時間でした。
- とりあえずindex
alter table entry add index updated_at(updated_at);
- トラップを踏んだのか何なのか、新卒陣がPerlのローカル環境を動かせずに断念。以後「動け!!!🙏」と念を込めてプルリクすることに。ちょっと凹んだ。
- 明らかに
htmlify
が重いので、とりあえず Regexp::Trie を導入するもあまりスコアは伸びず。 - 毎回生成してるから重いのでは…ということで
entry
のidを覚えておいて更新があったときだけ再生成するように変更。
(この時点で最大スコア20000程度。いまいち伸びず内心結構焦ってました…。)
- 正規表現をRedisに入れるようにして、
htmlify
で正規表現を作るのはやめて、entry
がpostされる時に再生成するように変更。が、同時リクエストでRedisの値の整合性が取れずベンチがこける。 - post entry用のプロセスを立ててnginxから対象のパスは専用のそちらの1プロセスでさばくように変更。この変更で15時前頃にスコア80000くらい。一気に上位に食い込んでやる気が…!
やる気出てきた #isucon
— fujiwara (@fujiwara) 2016年9月18日
うおおおおおおおお
— もし (@moshisora990) 2016年9月18日
- この頃に
/
でSELECT COUNT(*) FROM entry
していたところもRedisにのせましたが、スコアは若干上がった程度でした。
このあたりから、プロセスを生かしたまま2度目のベンチを回すとスコア120000くらい出ることに気付きながらも原因についてはこの時点ではよくわからず。
同時に、 "上町村" に "川上町" からのリンクがありません (GET /keyword/川上町)
というメッセージが出始め、「なんでしょうねこれ」とはなりながらも、運営へ質問したところ Status: PASS
ならスコアは有効ですとの回答を得られたのでとりあえず無視。ぬか喜びしていた時間帯。
15:00〜17:30
スパムチェッカーがCPUを食っていてしばらくワード等ログに出して見てはみたものの、NG判定されているワードも規則が見えなかったのでここのテコ入れは断念。
あまり突き刺さる変更はできなかったものの地道にスコア更新。細かいものも色々。
/
のentries
のクエリを自己結合に。/stars
をRedisにキャッシュ。initialize
でstars
を全部Redisに載せてget_multi
するように変更。uri_for
が遅いらしい&絶対パスにしなくてもベンチ通る。ので全部消す。(たぶんほとんど効いてない)- user_nameもsessionにいれて
set_name
のクエリ削除 - とかとか
ここまでで初回ベンチスコア90000くらい、何度か回すと最大スコア170000くらい(まだ謎でした)。
17:30〜18:00
post entry用に立てたプロセスをrestartするとスコアが90000程度に戻ってそうだと発覚。どうやら Trie
オブジェクトが生きたままになっていて、1度目のベンチで追加したキーワードが2度目のベンチでも効いていた模様でした。ここでようやく謎が解けた。30分前。
(なので、ないはずのリンクが作られていた模様。川上町の謎が解けた…)
ならば、ということで、一度ベンチを走らせて追加されるデータをテキストに落として、 initialize
時に正規表現に追加しておくという実装がfujiwaraさんによって高速挿入されてコード変更は終了。完全に未来予知作戦なので本質的ではない&データセットが変わると全く効かないので、複雑な気持ちですねーという話をしながらではありつつも、これで140000点を突破(17:50頃)。
その後再起動してベンチキューに滑り込み、終了3秒前にベンチ実行開始。稼働状況を見る感じ大丈夫かなあ…という雰囲気でしたが、再起動後のスコアを確認できないまま競技時間終了…。
ギリギリもギリギリだった…
予選突破できた
不安な感じで競技終了時間を迎えてしまったので反省会中もdkdkしていましたが、最終スコア143,366で無事通過できました。とはいえ最後の裏技的なやつが効いてなかったら9万点いくかいかないかくらいだったので、結構やばかったんじゃないかなと…。
- Perlのコード書く以外やってない。要復習。
- htmlifyもっとなんとかできた気もする…。
- 手元でPerl動かそう…(重要)
- 普段やってないことをやると結構単純なことで詰む。全部一瞬で拾ってくれる大先輩心強すぎる…。ありがとうございました。(自分でできるようにならないと…)
- (普段仕事でJSばかりなためか、JSのコード書いてボンゴレ氏に「それJSですよ」って突っ込まれた。手が…手が…)
大会の製作・運営のみなさま、ありがとうございました!初参加でしたが楽しかったです。ベンチマークも数分で実行されて快適でした!
そしてチームの皆様、本当にありがとうございました!ものすごく連れて行ってもらった感が否めないですが、何はともあれ予選突破できました。突破されたみなさま、本戦でお会いしましょう!!本戦は勉強じゃない、戦争だぞ!!との激励もいただきまして、一ヶ月頑張ります。がんばります…
さいごは反省会の様子です。弊社golang実装組がなかなかつらそうでした。正規表現…
すごいのきた pic.twitter.com/K6WST8tWY0
— もし (@moshisora990) 2016年9月18日