向かい風が追い風に変わってISUCON10予選を学生枠ギリギリで通過した

向かい風が追い風に変わってISUCON10予選を学生枠ギリギリで通過した
TaKO8Ki
September 14, 2020

こんにちは、TaKO8Kiです。 今回ISUCON10に参加したので、その振り返りとしてこの記事を残します。 結果からいうと、学生枠5位ギリギリで予選を通過することができました!

今回がISUCON初参加なので、予選通過できたのは非常に嬉しいですが、色々心残りもあるのでその点を中心に書いていこうと思います。

当日の流れ

使用言語はGoです。Rustでやってみたかったけど、流石に冒険すぎた。。 10:00開始予定でしたが、環境構築に時間がかかっているとのことで12:20開始に変更されました。

使用したリポジトリ: https://github.com/k-nasa/isucon10/

12:20 ~

ISUCON10スタート!ということで、まず最初にチームメンバー全員で5 ~ 10分くらいマニュアルを熟読しました。見落とすことが無いように声に出しながら読みました。

その後、意気揚々とサーバーにsshしようとしたら1台目、2台目に入ることができず。。(3台目も多分無理だろうと思って確認しなかったが、ここで確認しておくべきだった)とりあえず運営に質問を投げておいて、一旦はsshするのを諦め、マニュアルを読むのに徹することにしました。

12:50 ~

ここで先ほど確認しなかった3台目のサーバーにはsshできることに気付きました。(もう少し早めに気付きたかった。。30秒もかからずに確認できることはその場で確認しよう。)この時点では先ほど運営に投げた質問の解答はまだきてなかったので、サーバー3のsetupをすることに。 @nasa が事前に用意くれていた セットアップスクリプト を走らせて諸々のセットアップをしました。

これまた @nasa がよくやるオペレーションを書いた Makefile を事前に用意してくれていたので、それを使ってalpでログをみたりするなどしました。

@nasa がセットアップをしてくれている間に僕はコードを読んで明らかにN+1になっている箇所やどんな感じに複合indexを貼れば良さそうかなどをコメントに書いてPR( #5 )を出しました。

お互い別々のことをやっていたのである程度キリの良いところでzoomで画面共有して情報共有しました。言葉だけで済ますよりもペアプロっぽく同じ画面をみて話す方が理解度が全然違うと思うのでこのやり方はとても良かったと思います。

13:50 ~ (468点)

やっとベンチを回しました。Goで468点くらい。( その時の計測ログ )

DBが重たいことは分かっていたけど、マニュアルにbotからのアクセスがあるということとbotのUser-Agentの形式が示されていたのでまずそれを弾くようにし始めました。

この辺りで運営に投げた質問(サーバー1、2にsshできない件)に回答がありました。鍵の配置をミスっていたらしく、それを修正してくれたという内容でした。 いざ、サーバー1、2にsshだ!ということでやってみるとsshはできましたが、大量のエラーが出ており、まだ何かミスがあるのでは?ということで再度質問しました。

15:18 (580点とかだった気がする)

indexハリハリ。スコアは正確ではありません。

15:20 (618点)

nginx.confの設定を変更してbotの場合503で返すようにました。( #9 ) 思ったよりスコア上昇せず。

15:49 (618点)

最初コードを読んだ時にbulk insertにしろと言わんばかりの箇所があったので、POST /api/chairPOST /api/estate内で行っているinsertをbulk insertするようにしました。( #11 )スコア変わらず。思っていたよりinsertするレコード数が少なかったかもしれない。

17:20 (1008点)

searchEstateNazotteのN+1を解消しました。( #13 )おそらくこのあたりで1000点を突破したと思います。

/api/estate/nazotteのクエリが明らかに重そうだったので、アプリケーション側で計算できないのかなーと思っていたんですが、ライブラリ探したり、そのライブラリがちゃんと使えるか確かめるのに時間がかかりそうだったのでやめました。終了後他チームで golang-geo を使ってやっているのを見かけたので意外とすんなりできたのかもしれないです。

18:28 (1236点)

当初からやろうと思っていたDBとwebappの分離を行いました。それに伴い、各アプリケーションサーバーでの整合性をとるためにinitialize処理だけを行うエンドポイントを生やして、/initializeの中でそれを叩くようにしました。( #12 )

18:30 ~

この辺りで思いつくことは実装しきってしまい、次何しようか?という話をしました。 以下の案が出て結果的に残りの時間で2、3をやることにしました。

  1. chairとestateでDB分ける
  2. /api/chair/search/api/estate/searchをオンメモリキャッシュする
  3. MySQLのバージョンを上げてみる

また、 @nasa がmysqlのquery cacheがOFFになっていたのでconfigを修正してくれました。しかし、うまくONに出来なかったためこれは断念しました。

19:00 ~ 20:00 (600点くらい)

@nasa がMySQLが5.7なことに気づき8へのアップグレードを行ってくれましたが、スコアは半分くらいになってしまいました。

configファイルを見て設定を付け足すのなどしたけどよく分からず、結局5.7を使うことにしました。また、この時サーバー1でバージョンアップのデバッグをしていたので、DBサーバーをサーバー3に変更する修正を行いました。( #16#17 )

20:00 ~

流石に再起動試験の確認をしないといけない時間になってきましたが、先ほどの「/api/chair/search/api/estate/searchをオンメモリキャッシュする」( #15 )というのがまだ終わっていなかったので再起動試験の確認はしないことにしました。

20:30 (1170点)

キャッシュの実装できた!と思ってベンチを回したら整合性チェックで落ちてしまったので断念しました。(時間かけたけどスコアに繋がらなかったのでなんとも言えない気持ち)DBの分離のことはすっかり忘れていました。今からDB分離の実装をやるのは流石に無理と判断し、nginxの設定を変更してwebapp3台、DB1台の構成に変更しました。しかしスコア変わらず。

そして終了!!!

21:00 ~ 23:00

終了してから1、2時間くらい「なぜDB分離に踏み切らなかったんだ。。」という話をしてた覚えがあります。DiscordのrandomチャンネルをみてるとDB分離したら一気に上がった!という声が多かったのでやりたかったです。

予選突破チーム発表

どこが本戦に行くのかなーと思いながらYouTube liveを見ていたら、学生枠5位ギリギリでチーム名が呼ばれて驚きました。運営の皆さん、遅い時間までありがとうございました!

振り返り

競技について

前半は2時間ほど二つのサーバーにsshできなかったりした割には冷静にその時できることをやることができたと思います。その後DB分離に踏み切ることができなかったのは少し後悔が残りますが、残り時間がなく焦っていたことも踏まえると仕方ない部分もあると思います。

結果について

ISUCON10 予選結果と本選出場者決定のお知らせ にもあるように僕たちのチーム「アサシン」は学生枠5位でした。発表前の順位を見ている限りでは学生枠に2、3位足りなかったはずなので、上位のチームが再起動試験に失敗したり、最終スコアで予想通りのスコアを得ることができなかったりした結果、滑り込めたのだと思います。(再起動試験に通っていたのもまぐれ)本戦に参加できることは嬉しいですが、社会人枠で本戦通過できる実力を付けるために精進しようと思いました。

ということで「序盤はsshできなかったりしたけど、結果的に運に恵まれてISUCON10予選を学生枠ギリギリで通過した話」でした。