ISUCON6にmorimoto組で出場して準優勝でした
ISUCON6に出場しました
ISUCON6本戦@渋谷ヒカリエ LINE株式会社
ISUCON6に「morimoto組」で出場して、準優勝できました。メンバーは、
という布陣でした。言語は自分とボンゴレ氏がPerlの方が使い慣れている関係でPerlを選びました。
スコア推移
ラスト1時間は他のチームのスコアが非表示ですがこんな推移でした。一台でチューニングしてから最後に複数台構成になったので結果発表ではダークホース感があったかもしれません…。
Time | PASS/FAIL | Score | 変更 |
---|---|---|---|
11:02:53 | PASS | 942 | Perl初期スコア |
11:21:28 | PASS | 1159 | |
11:58:31 | PASS | 1364 | |
12:31:15 | FAIL | 253 | |
12:36:34 | PASS | 1616 | |
12:39:18 | PASS | 2051 | nginx導入 |
12:43:40 | PASS | 3175 | perlのプロセス数を200に(していたらしい) |
12:46:41 | PASS | 3543 | |
12:49:26 | FAIL | 12 | |
12:53:18 | PASS | 2816 | |
13:03:36 | PASS | 3314 | |
13:35:14 | FAIL | 251 | |
13:47:46 | FAIL | 251 | |
14:07:14 | PASS | 3211 | pointsをstrokesのカラムにjsonで保存するように |
14:09:41 | FAIL | 0 | |
14:10:56 | FAIL | 0 | |
14:11:25 | FAIL | 0 | |
14:14:25 | PASS | 3470 | |
14:15:21 | FAIL | 0 | |
14:16:38 | FAIL | 0 | |
14:20:25 | FAIL | 0 | |
14:24:03 | PASS | 4697 | /img/* で返すSVGをPerlでレンダリング |
14:27:05 | FAIL | 252 | |
14:29:53 | PASS | 4781 | |
15:17:25 | FAIL | 106 | |
15:21:32 | PASS | 7412 | /img/* をRedisにCache |
15:31:52 | PASS | 6040 | |
16:09:04 | FAIL | 253 | |
16:10:24 | FAIL | 253 | |
16:12:32 | PASS | 8020 | |
16:54:56 | FAIL | 253 | |
16:58:52 | FAIL | 253 | |
17:10:31 | PASS | 9339 | /api/stream/rooms をRedis pub/subとGo実装に置き換え |
17:41:33 | PASS | 15241 | 2台構成 |
17:43:36 | PASS | 30714 | 5台構成 |
17:45:12 | PASS | 29301 | isu02再起動試験 |
17:48:35 | PASS | 36067 | isu01にnginx,MySQL,Redis、その他でPerl,Go,Reactの5台構成 |
タイムライン
10:00~12:00
開始間も無くしてAzureへのデプロイがうまくいかなかったり、アプリを読んだり触ったり、Perl実装を反映してベンチをかけるまでに1時間ほどかかりました。その後手元でperlのサーバを動かしたりと準備をしているといつの間にかお昼頃に。
12:00~15:30
pointsをstrokesのカラムにjsonで保存
points
は一点ごとにレコードになっていて、必ず strokes
と一対で、かつ更新もなさそうだったので、これは strokes
と一緒にしてしまっていいよね、ということで strokes
テーブルにカラムを追加して、そこにjsonで入れることに。同時に、初期データもjsonに変換するスクリプトを書いて strokes
のカラムに保持、としたもののこの時点ではあまり効果は無し。
/img/* で返すSVGをPerlでレンダリング
SVGの生成はReact側からperlのAPI経由で points
のjsonを取得して、React側で表示するSVGを生成していたので、これをperl側で生成するようにする実装が、残り2名で points
の変更を入れている間にfujiwaraさんにより導入。
/img/* をredisにcache
stroke
が新たに追加されるまで、 /img/*
の結果は更新する必要がないので、これをredisにcache。新たに stroke
が追加されたときにキャッシュを破棄するように。これで結構伸びて7412。
15:30~17:10
この時間が苦しかった…。
/api/stream/rooms
をRedis pub/subとGo実装に置き換え
200プロセスでゴリ押していた stream
がやはり辛いという話になり、この部分の実装をGoに置き換えることに。Perl側から新しいstrokeの投稿があったときにstrokeをpointsと一緒にpublish、Go側でsubscribeしてクライアントに配信するように変更。この変更でPerlでは500msごとに新しいstrokeをまとめて送信していたものが、新しいstrokeが来るたびに送信できるように。一旦は完成したかと思いきや、ベンチを走らせると 必要なwatch_countが送信されていません
旨のエラーメッセージでベンチが通らず、しばらくこれの解決に食われましたが、ボンゴレ氏が、「これ、publishされなくても500msしたら返さないといけなくないですか?」と閃いてなんとかベンチ通過。パフォーマンスも改善して9339。
新しいstroke投稿があったときにすぐ送信できる実装自体はあまりスコアに影響がないらしかったですが、触ってみるとレスポンス早くなっていいアプリになった感じはありました。余談です。
strokes
countもredisにcache
毎回 stroke
を全部拾ってきて scalar
で個数だけ拾っている部分があった
$room->{stroke_count} = scalar @{ get_strokes($self->dbh, $room->{id}, 0) };
ので、これもredisに
my $stroke_count = $redis->get('stroke_count'.$room->{id}); unless ( $stroke_count ) { $stroke_count = scalar @{ get_strokes($self->dbh, $room->{id}, 0) }; $redis->set('stroke_count'.$room->{id}, $stroke_count); } $room->{stroke_count} = $stroke_count;
stroke
投稿時に incr
: $redis->incr('stroke_count'.$room->{id});
というものは書いてはいたものの、時間が差し迫っていたのでmergeしないまま複数台構成作業へ。
17:10~18:00
コードはフリーズして、複数台構成と再起動試験。
fujiwaraさんにお願いしてあとは自分たちは祈るだけという状態に。
最終的には isu01
でnginx, MySQL, Redisを動かしてそれ以外でPerl, Go, Reactをのせました(競技後に教えてもらいました)。
isu02
の再起動試験をしたのち、最終的な構成にしてスコアは36067。最後に isu01
を再起動はしたものの、これ以降スコアが伸びることもなさそうだったのと、時間が終了5分前くらいだったこともあり、これでスコアfixしましょうということに。ベンチは実行しないまま、各自 isu01
につないでちゃんとレスポンスが返ってることだけ確認してそっとコンソールとブラウザを閉じました。
結果
最終スコア 36067 で準優勝でした。
反省はやはり、コードくらいは2人でがんばるぞ!!で、fujiwaraさんに下回りをお願いするのが理想形だったと思うのですが、結局結構コードも書いてもらってしまったことと、Go慣れしてなくて選択肢も最初から絞り気味だったことでしょうか。お題を聞いた時点でPerlつらいしGoよさそうという話はあったのですが。golang書こう…
結果は嬉しいものでしたが、ブログを書きながら振り返ると、肝心なところは全部先輩頼りでしたし、16時を過ぎたあたりからは何やれば良さそうかも分からなくなってきて、個人的にはやはり全然戦えてないなーという感想で、悔しくも感じた初参戦でした。悔しさ胸に勉強せねば…
出題・運営の皆様、予選も本戦も、楽しい問題と競技を本当にありがとうございました。また協賛の皆様、楽しい懇親会をありがとうございました!
そしてチームの皆様、本当にありがとうございました!すごい体験をさせていただきました。嬉しくも悔しくもありましたがこれを糧にまた頑張ります。
最後にこちらを!
ISUCON6裏話Nightに酒を贈りたい方はこちら→ https://t.co/2mxdarwDKf
— edvakf (@edvakf) 2016年10月23日
おや…? #isucon pic.twitter.com/PF2DpxwJ9n
— ISUCON公式 (@isucon_official) 2016年10月22日