ISUCONという面白そうなイベントが存在することを知ったので参加してみました。

最終スコアは45870点で全体で85位、学生で10位でした。

準備

10と9の予選問題を触ってみました。

ベンチマークまで含めて一台で行ってしまったのでDB分割等の練習はできませんでしたが、何を参考にチューニングを進めるか程度は決定できました。

練習時間もそれぞれ半日程度しか取れなかったこともあり、SQLにインデックスを少し貼る以外はアプリケーションのチューニングをメインにしてDB等の入れ替えは避けたほうが良さそうだと感じていました。

また、GitHubで管理してwebhookで簡単な自動デプロイを組むことも決めました。

当日

チームメンバーとの連絡にはDiscordのVCを利用していたため参考にできる記録がGitしかなくズレがあるかもしれません。

10:00 最初に20分程度で自動デプロイの設定を入れるつもりでしたがポートが空いていない等の問題もあって結果として最初の準備に1時間程度かけてしまいました。

11:00 ようやくpprofを導入して最低限計測する準備が整ったのでベンチマークを回し、ボトルネックを探し始めました。

トレンド取得に時間がかかっていて確認するとN+1がありましたが、ドキュメントを確認すると/api/trendは反映が遅延しても問題なく、その時間に制限もなかったため初回にのみ取得してそれを返却するように変更を行いました。

12:00 CPU使用率が100%となってしまうのでAP+DBの二台構成にすることにし、そのための変更を加え始めました。

事前に複数台使った練習を行っていなかったため、複数台存在する場合の初期化処理がうまくいかず、ベンチマークで何度かfailしつつ12:50頃に2台構成に変更ができました。 この変更によって大幅にスコアが増加し、17000点程度になりました。

これ以降何度かdropProbabilityに変更を入れてスコアが上がらないか試しましたが下がってしまうので最終的に0.9になりました。

13:00 お昼ご飯を食べていたので無し

13:50 nginxのCPU使用率が25%*2となっていて、かなり大きな部分を占めるようになってしまったのでUnix Domain Socketを使用するように変更を行いました。

14:00 DBを別にしたことで早くはなりましたが、POST /api/condition/:jia_isu_uuidに時間がかかっていたのでNamedExecでbulkinsertを行うようにしました。

14:20 ファイル読み込みにも多少時間がかかっていたのでアセットの配信をnginxで行うように変更

15:30 getIsuListでtimestampを利用したソートが遅かったのでidを利用したソートにできるように変更。

各isuは常に新しい時刻のものを送信するため、各リクエスト内でtimestamp順にソートを行った上でDBに追加するようにしました。

16:00 アプリケーション+nginxにはまだCPU使用率に余裕があり、DBはCPUを100%まで使用する状態となったので、isu_conditionテーブルのみ2台のDBサーバーに分割することにしました。

各uuidの最後の一文字を利用してDBの振り分けを行うようにし、このときに不要と思われるトランザクションを使わないようにもしました。

これによってスコアが3万点程度まで上昇し、学生3位に一瞬入りました。

スクショ残ってました

16:40 後述するミスのせいで1つ目のDBサーバーのCPU使用率に余裕がある状態にも関わらず、リクエストが来ずにベンチマークを回すたびにスコアが減少する状態となってしまい原因が分からず数カ所変更を加える。

17:20 ミスに気づかないまま中断となってしまう。

リクエストが来ない状態だったのでベンチマーカーの問題だと考えてしまった。

18:10 再開後何度ベンチマークを回しても1000点前後になってしまうようになった。

18:34 終了直前になってミスに気付きました

追加した2台目のDBに対して正常に初期化処理が走っておらず、ベンチマークを回すたびにそのデータが残り続けて極端に遅くなっていました。

1台目のDBの方が若干負荷は高くなるはずだったのでそちらのCPU使用率しか確認しておらず、保存されているデータもこのタイミングで確認していなかったことが原因でした。

18:37 上記のバグ修正

18:43 ログを取るために入れていたものの停止、削除

18:44 自動デプロイ用スクリプトの停止

18:45 再起動や環境情報の確認を行えないまま終了


改善すべきこと

全てのサーバーの状態を確認できる環境を整えるべきだった。

これをしなかったことで一時間以上無駄にしてしまった上に再起動の確認も行えず、今回は運良くfailしませんでしたが複数のボトルネックの改善も行えずに終わってしまいました。

分担を全く決めていなかった

git管理でも決めておかないとどこに手を着けるか考えて時間を取られてしまう

pt-query-digestを使用したものの役に立てなかった

練習時に一度も使っていなかったのに導入してしまったことであまり参考にできなかった。

DB、nginxのconfigの調整まで手が回らなかった

事前に何も調べていなかったので時間が無い状況では変更する余裕が無かった。

普段あまり使わないMariaDB/MySQLはともかくnginxはチューニングしたかった

indexをほとんど貼れなかった

複合indexを知らなかった

今回は準備不足な感じがあったので次回はもう少し事前に時間を取りたいです。