こんにちは
8/21 に行われた ISUCON11 の予選に@masibw くんと@tosa_now くんと一緒にチーム「雑談係」として参加しました。
これまでのチームの戦績は isucon10 は泣かず飛ばず、NTT Performance Tuning Challenge はかなり調子が良かったものの再起動試験で失敗し、0 点という感じでした。
ISUCON11 @tosa_now @masibw とギリギリ本戦出場滑り込んだ〜〜🥳 pic.twitter.com/jibBoUNImt
— さんぽし/sanposhiho (@sanpo_shiho) August 22, 2021
役割分担
僕はインフラ係として 複数台分散を含む、nginx と mysql のお世話をメインの仕事としつつ、隙間時間に他を手伝う遊撃手として動いていました
時系列やったこと
他のチームメンバーがなにをやっていたのかは大きな影響が出たもの以外はあまり知りません。僕がやっていたことを中心に記載します。
競技開始
競技開始と同時に色々ツールを入れました。
無難に
- alp
- pt-query-digest
- pprof
あたりを使っています
開発フローとしては
- git で master に PR が merge される
- CI/CD(僕)が必要なサーバー上で master を pull する
- CI/CD(僕)が必要なサーバー上で Go をビルドし、再起動
- CI/CD(僕)がベンチを回す
- CI/CD(僕)が必要なサーバー上で alp や pprof、pt-query-digest を実行
- CI/CD(僕)が 5 の結果を slack に投げる
という流れで人力 CI/CD という名の僕が頑張ることにしていました。といってもかなりの部分は Makefile に記載しており、そこまで手間なわけではありません。
index 張る + logger 消す
チームメンバーが index を入れてくれ、初期スコアから点数が一気に伸びました。
app の logger (middleware.Logger 含む)もどうせみない(&& app の細かいログをみたくなるくらい詰まった時に戻せばいい)ので、丸っと全部消しました。こっちも意外と 5000 点くらい上がった記憶があります。
複数台構成
去年は人力 CI/CD の手間が増えたり、app サーバーを分散した場合全ての pprof を上手く取れなくなるため、複数台構成を最後の方に残していましたが、ギリギリに複数台構成で詰まって大変だったので、今年はさっさと複数台構成にしました。
app 1 台 + DB 1 台になりました
ここでもちょびっと点数が上がりました
bulk insert
今回は以下のようなレギュレーションの記載がありました。
https://github.com/isucon/isucon11-qualify/blob/main/docs/manual.md
POST /api/condition/:jiaisuuuid で受け取ったコンディションの反映が遅れることをベンチマーカーは許容しています。以下のエンドポイントが該当します。
GET /api/isu GET /api/isu/:jiaisuuuid/graph GET /api/condition/:jiaisuuuid GET /api/trend
ただし、 GET /api/condition/:jiaisuuuid と GET /api/isu/:jiaisuuuid/graph の間で取得できる情報は 1 秒以内に整合性を保つ必要があります。 たとえば、GET /api/condition/:jiaisuuuid で取得できたコンディションは、 1 秒以内に GET /api/isu/:jiaisuuuid/graph でも取得できなければいけません。
そのため、POST /api/condition/:jia_isu_uuid
を bulk instert に実装し直しました。
具体的には
POST /api/condition/:jia_isu_uuid
ではオンメモリの配列にisu_condition
を追加する- オンメモリの配列は 500ms ごとに bulk insert される
という流れです。
配列に isu_condition が溜まりすぎるとエラーが出るため、毎回 1000 件ずつ bulk insert するようにチームメンバーが途中で修正を入れてくれました
また、too many open files
に引っかかったためユニット設定ファイルからファイルディスクリプタ数をあげました
bulk insert 周りのコードはこんな感じ
https://github.com/masibw/isucon11_qualify/blob/master/go/main.go#L1289-L1410
app を 2 台に
bulk insert で app の負荷が上がったので app を 2 台にしてPOST /api/condition/:jia_isu_uuid
のみを片方のサーバーに流しました
これで app 2 台、DB 1 台になりました。
ここまでで bulk insert と合わせてかなり効果があり、ぐっと点数が伸びました
N + 1 の改善
いつの間にかましくんがやってました。どこの何の N + 1 を潰したのか知りませんが、めっちゃ点数が上がりました
/assets を nginx から配信
Go から配信していたので nginx から直接返すようにしました。
dropProbability を 0 に
bulk insert を実装して「いけるんじゃね? w」くらいのノリで dropProbability を一気に 0 にしました。
他のチームの話を終わってからみていると dropProbability を 0.9 に戻したりすると点数が上がったとかって話もあるので一気に 0 にはすべきではなかったかもしれません。
競技時間内の最終結果
他のチームの結果が見られなくなる時点(17 時)での得点は最高点が 60352 点、最新点数が 53688 点で順位は学生 2 位、全体 22 位でした
「まあ多分大丈夫しょ! w」と考えた僕たちは安全策をとって、ここから先は現状の実装の不安定な点をちまちま潰したり、再起動試験の確認をしたりし、新たな改善は加えませんでした。(この戦略のおかげで再起動試験に通ったのかもしれないが、この戦略のせいでギリギリだったとも言えるかもしれない。障害でポータルも閉じてたのにみんな意外と攻めるのね…)
そのため僕たちのチームはここから点数があまり変わっていません。
最終結果
学生枠の 5 位でした。あぶない〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
ISUCON11 オンライン予選 全てのチームのスコア(参考値)
見たところ、ベンチマーカーが変わったからなのか単に運が良く上振れたのかはわかりませんが、60327 点となっています。
終わりに
かろうじて突破できて良かった、本戦がんばります。