ISUCON14 に参加しました!
初めまして、バックエンドエンジニアの maya です。
この度、弊社スタッフでチームを組み、初めて ISUCON14 に参加しました!
本記事では、ISUCON の概要や準備、当日の奮闘、そして参加してみて感じたことなどをまとめたいと思います。
01 ISUCONとは?
ISUCON(Iikanjini Speed Up Contest)は、与えられたウェブサービスを題材に、そのパフォーマンスをどれだけ改善できるかを競うコンテストです。
参加者は、システムの設計やアプリケーションコードの改善、データベースやサーバー構成の最適化などを駆使してスコアを伸ばします。
2011年に始まったこのコンテストは、LINEヤフー株式会社を中心とした企業や団体が主催しており、学生から社会人まで幅広い層が集まる人気イベントです。
課題は、実運用を想定したリアルなウェブサービスをモデルにしており、スキルアップや新たな知見を得られる絶好の機会となっています。
また、上位チームには豪華な賞品や特別な表彰が用意されており、参加者のモチベーションをさらに高めています。
02 経緯
元々、私がISUCONに興味を持っており、社内で「興味がある人はいませんか?」と声をかけたところ、「面白そう」と反応してくれた takano、そして参加登録の報告にリアクションをくれた kuriyama がメンバーとして加わってくれることになりました。
参加メンバー
- maya(私)/ 今年入社した S2 の新人バックエンドエンジニア
- 担当: アプリケーションと DB 最適化
- takano / テクニカルディレクター
- 担当: アプリケーション開発と Redis 移行
- kuriyama / インフラエンジニア
- 担当: インフラ構築と環境整備
03 準備
初参加ということもあり、具体的なイメージがつかない部分が多かったため、まずは他チームのブログを読み、当日にどのようなことを進めればよいか考えるところから始めました。
また、公式サイトの ISUCON 初心者向け講習会を参考に、必要なツールや基本的な進め方を確認。
競技言語については、事前の調査で「Go言語での参加者が圧倒的に多く、公開されている知見も豊富」という認識がありましたが、以下の理由から普段業務で使用している Node.js を採用することにしました。
- 日々の開発で使い慣れているため、短時間で最大限のパフォーマンスを発揮できると判断
- 競技を通じて得た知見を日々の開発に活かすことで、業務に良いフィードバックを得るため
使用するフレームワークについても検討を行い、業務でよく使用している Express.js をベースに考えつつ、過去問で採用例のあった Hono にも触れ、選択肢を広げました。
準備段階から各自でツールや技術のキャッチアップを進め、当日スムーズに動けるよう備えておきます。
方針
大体 2 週間に一度のペースで定例を実施し、以下のような方針を共有しました。
- 1 台構成でのチューニングから始め、後で複数台構成に移行する。
- DB を PostgreSQL に切り替えるかどうかは当日の課題次第で判断する。
- 担当分けを以下のように決定。
- アプリケーションは maya と takano
- インフラは kuriyama
- 運営からの連絡は maya が担当
- スコアの目標として、最初のベンチマークスコアの10倍を設定。
04 当日
今回の課題は、「ISURIDE」という架空のアプリケーションのパフォーマンス改善でした。
ISURIDE は、アプリで椅子を呼び、その椅子に座って自動運転で目的地まで移動できるタクシーのようなサービスです。
当日は3人とも寝坊することなく、時間通りに集まりました(3 人とも普段から朝型勤務なので0回戦敗退の心配はしていませんでしたが)。
kuriyamaと私はオフィスから、takanoは自宅からリモートで参加。
オフィスでは、kuriyamaが「ハック系イベントといえばドーナツ」とおやつを買ってきてくれました!
Zoomで集まり、公式配信を見ながら課題の確認をしたのですが、課題のクオリティの高さに驚きます。
競技中の取り組みは、午前中に環境構築やデプロイの自動化、ドキュメントの確認を進めながら、すぐに対応できる箇所に着手することから始めました。午後からは、サーバーを複数台構成に変更し、スコアアップを狙う流れに移行。
以下は、時間帯ごとの主な作業内容です。
午前
- 10:00 - 環境構築とドキュメント確認
- kuriyama が早々に環境構築を開始。
- takano と私はアプリケーションのドキュメントを読み進め、肝になりそうな「マッチング機能」に注目しました。
- 最初のベンチマーク(SCORE: 970 を回し、Node.js に切り替えて 553 からのスタート。やや苦戦の予感。
- 11:00 - ツール導入と DB 最適化の開始
- kuriyama は「pt-query-digest」や「alp(Access Log Profiler)」などのツールを導入。
- takano が DB インデックスの追加を開始し、Redis へのデータ移行に着手。
- 私は esbuild を試すも依存関係の問題で断念。スコアは 763 に微増。
午後
- 12:00 - 本格的な最適化作業へ
- takano は DB アクセスの最適化を進め、私は別の DB クエリをチェックしてインデックスを追加。
- kuriyama は CI の整備を進め、システム全体の効率化に貢献。
- スコアは 1721 まで向上し、喜びの声が上がる。
- 13:00 - サーバー分離構成へ移行
- takanoが椅子の現在地をDBに保存し、ユーザーを距離が近い順にマッチングするようプログラムを修正。スコアは 3212 に上昇。
- 全てを 1 台に載せていた構成から、サーバーを 3 台に分離する作業を開始。
- kuriyama が構成変更を準備。ドーナツを食べて糖分補給をしつつ、午後の作業に取り組む。
- 15:00 - さらなるスコアアップを目指して
- Redis を別サーバーに移行し、スコアは 4883 に上昇。
- MySQL も別サーバーに移行し、ベンチマークスコアは 5385 点に到達。
- kuriyama のスロークエリ分析を基に、takano と私はプログラムの調整を進める。
最終調整と結果
- 16:00 - スコア停滞と修正試み
- 各々クエリの最適化や環境調整を進めるも、スコアは6675で停滞。
- 一時的にリーダーボードで100位になり、記念スクショを撮る。
- 16:30頃から大きな修正を試みるも、ベンチマークでwarningが多発。
- 17:56 まで粘りましたが、結局安定した状態に戻し、最終スコアは5957で競技終了。
午後の取り組みの中盤、途中でリーダーボード(全チームのスコア表)を確認したところ、一時的に100位になっているのを発見。嬉しくて記念にスクリーンショットを撮りました。
05 参加してみて
18:00 に競技が終了。
配信を見ながら感想戦をしたところ、たくさんの改善点があがりました。一方で、参加してみて良かったことも同じぐらい出ました。
改善点
- 修正の試行錯誤中に別の修正の反映待ちが発生していたため、反映させるサーバーを分けることで待ちを解消するべきだった。
- デバッグ環境の整備が十分ではなく、手戻りが発生した部分があった。
- スコアの計算方法をより意識し、優先すべき修正箇所を絞り込むべきだった。
良かった点
- チームプレイを発揮できたこと
- サーバーを分けるタイミングを適切に判断できたこと。
- 作業に迷うことなく、最後まで手を動かし続けられたこと。
言い出しっぺの私としては、メンバーから「楽しかった」という感想が聞けたのが何より嬉しかったです。
普段の業務ではチャット中心のコミュニケーションが多いため、リアルタイムで話し合いながら 8 時間ひとつの課題に集中する経験はとても貴重でした。
また、当初の目標であった「初期スコアから 10 倍にする」を達成できたことにほっとしました。
最終スコアは 5957 点で、順位は 831 チーム中 292 位という結果でした。
まだまだ上は目指せると思うので、もっとレベルアップして、また来年も出場したいと思います!