Skip to content

Instantly share code, notes, and snippets.

@yami20
Last active October 5, 2020 06:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yami20/0dedc537f4baedecc54162867d9e298d to your computer and use it in GitHub Desktop.
Save yami20/0dedc537f4baedecc54162867d9e298d to your computer and use it in GitHub Desktop.
ISUCON10本選に参加し、総合4位/社会人のなかでは1位(笑)でKLab賞をいただきました。

それなりに善戦できたという達成感と、社会人チームがISUCON10の問題にどのように敗れたかのログを残したいと思います。

サマリ

  • チーム
    • 一口坂46
      • 株式会社FINATEXTの有志チーム。
      • チーム名はオフィスの前にある坂の名前を見て自分が適当につけた。
        • メンバーの作ったツール等が「47」になっていたりで全く浸透しなかった。
    • メンバー
      • s_tajima: インフラ,サーバー上でのオペレーション全般担当
      • atushi-ishibashi: 主にアプリケーション担当
      • 自分: 主にクエリチューニング担当
  • 順位/スコア
    • 順位
      • 総合4位、社会人チームの中では1位(笑)
        • 予選も4位だったのでここが限界感ある
    • スコア
      • 競技中ベスト/最終
        • 34342
    • 受賞
      • KLab賞(スポンサー賞受賞のない中で最高スコアチーム)

スコア非公開化までの経過

事前準備

事前にチームで過去問を問いたりはせず、各自ベストエフォートで準備しよ〜って感じでゆるく進めました。

チームとしてやったこと

  • 各自事前にパフォチューの手札(知識なりツールなり)を確認しておこうという話をした
  • 前日に各自準備した内容をかるく口頭ですり合わせた
  • 本番のタイムラインを確認した※予選と同じ
    • 最初1時間は環境のバックアップや計測の仕込み、レギュレーション理解、アプリの理解に努めよう
    • 最後1時間は再起動試験を念頭に置いた安定化に努めよう
    • くらい。

個人的にやったこと

本番前々日の夜と前日の午後に時間を取って以下のような準備をしました。

  • 本選過去問の講評を一通り読んでアプリケーションの規模感や複雑度、インフラ、ベンチマークの傾向などをざっと把握した。
    • 本選むずくない??っておもいました(小並感)
  • 手元の .vimrc がぶっこわれているのを数年越しで直した。
    • 予選中はSQLファイル編集するとフリーズするからとてもつらかった...。
  • 本番で使うかもしれないスニペットやaliasを前日の夜にいくつか書いた
    • 雑に悪そうなクエリや実装を探すgrep芸
    • DB関連の実装
      • DBの中身をselectしてgoの変数実装に変換するscript
        • staticなデータを実装に組み込んでテーブルを捨てるための仕込み。
      • シャーディングのgo実装
      • レプリケーション対応のgo実装
    • フレームワーク(echo)やよく使うライブラリの処理を短絡するためのsnippet

今回の課題/構成では有効に機能する感じでなかったので実戦投入しませんでしたが、心構えや指鳴らしにはなったからやっておいてよかったと思っています。

大会当日

自分がやったことを中心に、覚えている範囲でチームメンバーがやったことも織り交ぜながらざっくり書きます。

※なお余裕が全然なくて細かい作業ログとか残せませんでした...。なので実際とは結構違うかもしれません。

10:00(開始)~11:00

予定通り問題の理解や足場がためだけを行っていました。

レギュレーション読み込み

まずは初動でレギュレーション読み合わせ(音読)を実施しました。

説明の多さと、経験の薄いgrpcや未経験のWebPushの説明あたりで「これはやべーぞ」という空気になりました。

ちなみに席配置とかの関係で自分が音読したのですが長くてめちゃくちゃ疲れました...。

各種初期設定

自分はひとまずサーバーに入ってアプリをgit管理にしたのち、アプリの全体把握に務めました。

この間にenvoyやubuntu20であること、サーバースペックのバラツキなどをみたs_tajimaの悲鳴が聞こえた気がしますが聞こえないふりをしました。

11:00 ~ 13:00

atushi-ishibashiと分業でクエリ・アプリのチューニングに務めました。 s_tajimaはこの間にenvoyを捨ててnginx化し、いつもの土俵に持ち込んでいたようです。

最低限のindex追加

計測の体制は整いきっていませんでしたが、アプリケーション実装からクエリを一通り把握し、最低限貼っておくべきであろうindexを雑に追加しました。効果の程はわかりませんが、まぁ悪化したということはないはず...。

GET /api/audience/dashboardのクエリ簡略化

pt-query-digestの内容や実装から厳しいことが明らかなダッシュボードの集計情報参照クエリの最適化に着手しました。

観戦者向けのクエリの場合は不要な条件があるので専用のものとして切り出して簡略化しました。 当初はこのクエリの性能をもっとちゃんと測りながら踏み込もうと思っていたのですが、レギュレーションと挙動からここは雑なキャッシュで良いと判断できたのでs_tajimaに「merge後表側で1sec未満のキャッシュよろ~」といって丸投げしました。

このあたりの対応をまるっと含めてスコアは約5000点->10000点に伸びたようです。

13:00 ~ 13:45

スクリーンショット 2020-10-05 0 02 32

はい。

ベンチマークキューのクエリ省略

まともに経験のないgrpcサーバーの実装にキョドりつつ、queueの監視が高頻度でselect/lockを繰り返していそうなことを確認しました。挙動に確信が持てなかったもののダメなら切り戻そうという気持ちで

  • ロックを捨てて直接updateかける&AffectedRowsで存在判定
  • 監視頻度を低下させる

という実装を入れました。

一度エラッて微修正を加えつつ再度計測したところ、12015までスコアが伸びました。

13:45 ~ 14:30

参加チーム上限の緩和

自分は以下のような観点で少し手を止めて次の一手を考えることにしました。

  • 2人が忙しそうだった。
  • go実装まわりでコンフリクトが多くなってきそうだった。
  • 露骨なボトルネック/お手軽な改善ポイントが減ってきていた。
  • 上位チームのスコアが伸び始めて決定的な要因があるように思えた。

闇雲に目先の難解な実装に挑んで効率の良い要素を見落とすと怖いな〜と思ったので、この時点でドキュメントの読み直しを行うことにしました。

そこで、対応すべきものとして以下2点が重要そうであることを再確認しました。

  • 大会規模倍率
  • WebPush

「露骨なボトルネックが減ってきていた」ことを踏まえて、大会規模の設定値を上げるべきタイミングだと判断しました。 デフォルトの10から50->100->80と調整し、スコアが14000程度まで上昇しました。

14:30 ~ 17:00

スクリーンショット 2020-10-05 0 42 00

はい。

notificationのWebPush化

notification周りは実装そのものはそれなりに妥当な形でなされており、そこをちまちま改善して効果を得るのはなかなか難しいだろうという認識でした。 一方で先にも挙げたようにドキュメントにて WebPush化してもよい ことが示されていました。

トップとのスコア差と残り時間も鑑み、全く事前知識がなかったものの誰かがやらねばということで自分が着手しました。

ドキュメントのリンクからRFCも一応眺めたものの、完全理解を目指していたら日が暮れそうだったので WebPush 仕組み とか WebPush go 実装 とか検索していました。我ながらひどい。

ぐーぐる先生を頼りにざっと実装して動かしたもののベンチマークでfailしました。

手元でちゃんと試しながら調整しようとしてドキュメントを確認したところ、pushの検証用コードが用意されているということに今更気づきました。 このコードの一部を参考に実装を修正することで無事ベンチマークに成功しました。 その上でnotification短絡実装を加えて、スコア更新停止の17時直前に 18953 を記録しました。

17:00 ~ 18:00(終了)

安定化のお約束をしていた時間帯なので、自分の方ではリスクの低いクエリ改善やパラメータ調整の余地を探るくらいでした。 実際に作業としておこなったのは参加チーム上限を増減させて最終的に110にしたこと、DBサーバーの入れ替えのためにスキーマ適用のお手伝いをしたくらいです。

atushi-ishibashiによるアプリ改善をいくつかmergeしつつ、s_tajimaは仕込んでおいたサーバー複数台化やDB/Webの入れ替え、再起動試験に向けた設定の確認などを行い 34342 というスコアでフィニッシュしました。

ちなみにサーバー構成については予選でも本選でもアンバランスな構成への忌避感から2台しか使わなかったのですが、今回のappとサーバースペックのバラツキを思うと、まさにそのアンバランスさを活用できるポイントだったと思います。反省。

おわりに

まずは運営の皆様、参加された皆様、お疲れさまでした!おかげさまでとんでもなく脳汁あふるる8時間を過ごさせていただきました 😇

上位入賞は逃してしまいましたが、KLab様のスポンサー賞をいただく事ができ大変うれしく思っております。

上位を学生チームが独占という結果を受けて、社会人チーム的には立つ瀬のないところではありますが、企業のエンジニアと対等以上の技術力を身につける指標、そしてその実力を披露する場となっているISUCONの価値の大きさを感じました。

個人的には新卒2年目くらいでISUCON4?あたりに出て予選敗退した苦い思い出がありますが、そこから時を経てある程度の成長を示せたことに安堵しています。

チームとしてはFintechという(もしかしたら「どちらかというとレガシー寄り」「セキュリティだけが大事で性能はぼちぼち」と思われがちかもしれない)領域のエンジニアが新しいWeb技術と向き合って性能面でも戦えるということを示せたのは良かったかなと思っています。

改めましてISUCON10に関わられた皆様、本当にありがとうございました🙏

以下よもやま

文章としてまとめる体力がなかったけど雑多な感想を備忘的に残しておきます。

  • 問題のクオリティ&ボリュームが凄まじかった。
    • 仕事で半年くらいかけて作ってと言われても悩むレベル。
    • 「あと半日あればできること沢山あるのに...!」「どこから改善すべきか」という頭の悩ませ方はISUCONらしいなぁと思った。そんなに参加したことないけど。
    • envoyやgrpc,WebPushあたりの新しい技術、複数サービスの構成、ジョブキューなど切り口が多く総合格闘技感が良かった。
    • ベンチマーカーの精度と安定感がいい感じだった(気がする)。エラーもわかりやすく素直に丁寧だなって思った。
  • 仕様のリーディング時間ちょっと欲しかったなー。
    • 仕様が大きいけどちゃんと書かれていて、正道としてはもっと読み込んだ上でアプローチしたかった。
    • まともに把握しきるなら1時間以上欲しい量で、実装に手を付ける時間が無くなってぐぬぬ...って感じだった。
    • 「仕様の読み方」が競技の軸に入ったというか。そういう意味では問題のボリュームが大きかった(単に時間が少なかった)、と捉えるべきだろうか。
      • 出題側としてはどの程度時間をかけて読むことを期待していたのか気になる。
  • 若者すごい、率直にすごい。
    • 4位悔しい。3位でいいから/1社で良いから入賞したかった&してほしかった。
      • 我々としては短期的に打てる手をすべて加えていたとしても3位といい勝負くらいだったので、完全に自力負けだった。
      • どうやったらそんなに強くなれるんじゃ〜〜〜
  • 一方で、システム開発のトレンドとしてパフォチューの優先度が下がってきて企業内の力が下がっている側面もあるのかな、とかちょっと思った。知らんけど。
    • ハードウェア資源の低価格化/高性能化/資源追加の容易性
      • Lambda/CloudRun/ECS/GAE
      • Aurora/CloudDatastore(Firestore)
      • ...
    • 人的資源の優先度上昇
      • カリカリのシステムよりも、人に優しい(管理しやすい)システム
        • マイクロサービス、クリーンアーキテクチャ、...
    • 自分としても近年はチューニングがんばるというよりは、如何に資源を効率よく追加できるかという舵取りをすることが多い気がする。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment