😺

ISUCON13にチームOL001として参加しました

2023/11/26に公開

まえがき

ISUCON13にチームOL001のアプリケーション担当として参加してきました!
最高スコアは20,572、最終スコアは19,151で、全661チーム中108位でした!
自分目線でどういう改善をしていったのかをまとめていきます。
インフラ担当はまた別で記事を書いてくれるので、何をやっていたかはそちらで補間しながら見てください!

チームメンバー

OL001は今年結成したチームです。
社内で、やらんか?と声をかけたら一瞬でやる!と返ってきたので嬉しくなったのを覚えています。
メンバーは以下のとおりです。

名前 役割 ISUCON参加経験
@noko アプリケーション担当1 2回目
@yshir アプリケーション担当2 初参加!
@takeokunn インフラ担当 初参加!

当日のタイムテーブル

今回はオンライン参加です。通話はmeetを繋いで、作業者が画面共有する形で進めていました。
主に自分が関わったところについて時間ベースで触れていきます。

09:30 起床

無事起床成功。9:40には全員起きて集まっていた。
早起きできてえらい!

10:00 競技開始 4,198点

10:04くらいにはインスタンスが立ち上がり、 @takeokunn にプロビジョニングお願い!と投げた
10:06くらいに何も設定を変更せずにとりあえずベンチを回してみる。AWSのログインでちょっと詰まったところもあったが、それでも25番目くらいのベンチだったのが驚き。

10:10 動作確認

ブラウザでの動作確認とレギュレーションを読む。
ISUCON専用なのにこんなリッチなアプリ作れるの!?と感動していた。

10:20 計測

alp configをcopilotに書いてもらい、isucrudでupdate/insertを軽く確認する。
READMEにペッと貼っていますが、この情報が一発で取れるのは便利すぎる…!
https://github.com/OL001-isucon/isucon13/tree/main
nginxとmysqlのログを吐く設定を手動で入れ、改めてベンチを回す。
この時点でalpの上位にiconが来ていたのでなんとかしにいく。
ここから11時くらいまでプロビジョニングが完全に終わるのを待ちながら、コードとレギュレーションを読む。(裏側ではベンチの整合性チェックで落ちるようになってバタバタしていた)

11:45 iconの改善 5,386点

iconを画像としてファイルに書き出し、リクエストが飛んできたらそのファイルを読み込んで返すだけにした。
fillUserResponse でも画像を使っていることに気づかずちょっと時間がかかったが、1時間ほどで完了した。あとはnginxから画像を配信してもらうようにして改修完了。
練習で事前に画像を書き出すことはしていたので割りとサクサクできた。

12:30 reactionの改善に手を出す

fillReactionResponse で大量のN+1が生み出されていたので、なんとかしようと着手。
一発JOINしようとしたが、fill*fillReactionResponse の中でさらに呼び出されていることに気づき断念。色々と実験していたが、 fill* を @yshir がまとめて直してくれていたのであとを任せる。

13:00 ベンチが回らん

ベンチマーカー側に障害が発生していて、ベンチが回せず改善の手は一旦ストップ。
もし自分が運営側だったらと考えると焦りで冷や汗ダラダラだっただろうなと思う。本当にお疲れ様です。
この辺はreactionの改善を諦めたタイミングと大体被ったので、次のalp上位のものを改善しにいく。

13:50 statsの改善 14,067

16件しか叩かれていなかったが、明らかに遅かった statistics の改善に着手。
中身を、スパチャの額とリアクション数からユーザーのランキングを求める部分と、自分のライブについた諸々の合計部分へ、2分割して考えた。
ユーザーのランキング部分では頑張ってクエリ発行してスパチャの額とかを計算していたので、新しく user_stats テーブルを立てて、その中で諸々を計算するようにした。
MYSQLの TRIGGER を3つ生やしていたり、 GENERATE COLUMN を使ってみたりで結果的にはいい感じに修正できた。
過程は結構グダグダで、時間を取られまくっていた。

  • ランキングを求めるところでスコアが同じだった場合に name DESC で順位付けしなきゃいけないのになかなか気づけず、整合性チェックで落ちまくっていた。
  • リアクションもスパチャもしていないユーザーをランキングから除外していた( usersinsert に対する TRIGGERuser_stats にデータいれなきゃいけなかった)ことにも気づけなくてこれも整合性チェックで落ちまくっていた。

前半のユーザー部分を直した時点でalpの上位からは消えたので一旦改善を終了した。

16:00 moderateの改善 19,165

alpで上位に来ていた moderate の改善に着手。
NGワードの登録を行う部分だったが、見た瞬間に「馬鹿じゃないの!」と叫んでしまった。

  • 過去に削除済みなはずのNGワードまで毎回全部ループ回してチェックしている
  • そのループの中で すべての コメントを取得している
  • さらにコメントでループを回して %%LIKE 文で検索している
    と悪いところしかなかった。
    アプリケーション側でNGワードが含まれているコメントを検索するようにしたり、DELETE 文を一発で流せるようにしたり、NGワードが設定された配信のコメントだけ拾うようにしたりで無事改善した。

17:00 大きい改善は終了

細かい部分の改善を進める時間にして、 pt-query-digest の上位に来ていたクエリにindex貼ったりしていた。
このあたりから改善すればするほどスコアが下がっていくようになる。

17:30 DNSの水責め攻撃に気づく

ベンチマーカーの結果を見て、DNSの名前解決成功数があきらかに増えていることに気づく。
ここでマニュアルになんか書いてあったな〜と思い出すが、もう時間もないので目を瞑ることにした。
indexの追加をマージして最高スコアに 20,572 を記録して終了。
最後は祈ることしかできなかった。

17:50 祈り

気を整え 拝み 祈り 構えて ベンチを回す
一連の動作を一回こなすのに当初は1分~2分
一つのベンチごとに10分以上を費やした
ベンチが終われば計測をする 計測が終わればまたベンチを繰り返す日々

7時間30分が過ぎた頃 異変に気付く 点数が上がらない!
DNSの水責め攻撃が激化し、ベンチを回す手が止まる
かわりに 祈る時間が増えた
7時間50分を過ぎた時 ベンチマーカーはスコアを置き去りにした

よかったこと

  • 自分の改善でスコアを伸ばせた
  • 役割分担が良くできていた
  • 練習ができた・活かせた

自分の改善でスコアを伸ばせた

去年参加したときは自分の力でスコアを伸ばせたところがほとんどなく、無力を感じていましたが、今年は自分が改善した部分でスコアが伸びていたので圧倒的成長を感じました。
色々な問題の解決方法を実装してみて、引き出しを増やすことが大切だったなと思います。

役割分担が良くできていた

アプリ担当2人で改善箇所を宣言してから取り掛かるようにしてたので、お互い独立にそれぞれの改善を進めて行けたのが良かったです。
自分の改善でスコアが上がる→mainにマージしてまたスコアが上がるループが生み出されていてかなり気持ちよく実装ができました。

練習ができた・活かせた

練習はかなりの時間を確保できて、10/13 に1回目の練習を初めてからはほぼ毎日2~3時間ほど行えていました。
内容としては過去問の点数をひたすら伸ばす練習を最終週の前まで行っていたのと、最終週には本番と同じ想定での8時間練習を2回と立ち上げの練習をしていました。
この練習の中で色々なツールを試せたし、TRIGGERの使い方も知ったし、ファイルディスクリプタの設定とも戦えたし、得られるものが多くありました。
実際やったことなかったのは GENERATE COLUMN くらいで、本番ではほぼほぼ練習どおりのパフォーマンスが出せたと思っています。
長い期間仕事終わりの時間を拘束してしまいましたが、なるべく参加してくれたメンバーには大感謝です。

反省点

  • 実装のスピードが遅かった
  • わからんをわからんのまま終わらせてしまった

実装のスピードが遅かった

変なところで詰まって無駄に時間を使ってしまったところがあったのが最悪でした。
特にランキングの処理をよく追わずに実装して間違っていたところはもっと効率的にできたなと思います。
このあたりは過去問等を突き詰めることで実装の引き出しを増やすことや、コードリーディング力を高めることはしていかなきゃなと感じました。
statistics の後半部分改善とか、コメント・タグをキャッシュに乗せるとか色々やりたかったけど時間が足りなかったのが大きな後悔です。

わからんをわからんのまま終わらせてしまった

RDBMSについて未だに曖昧な状態で使っているので、効果的でない方法で変更しているんじゃないかという不安と常に戦っていました。
ちゃんと体系的に学んで仕組みを理解するところからやらなきゃなと反省しています。来年までにはもっとレベルを上げておきます。
また、PowerDNSが出てきてなにもわからん状態のまま終わらせてしまったのも良くなかったなと思います。この辺の知識を今からつけるのは難しそうですが、どうすればいいんだろう。
とりあえず来年までにDNSは攻略しておきます。

あとがき

初参加のメンバーが2人いたにも関わらず、初参加とは思えないレベルでもりもりスコアが伸ばせて楽しい体験になりました。
また来年もやりたいと言ってくれたので、パワーアップしてリベンジしたいと思います!
非常に楽しかったです!運営の皆さん、チームメンバーの皆さん、本当にありがとうございました!

Discussion