ISUCON12予選に挑戦してきました!
こんにちは。DFOの開発を担当しているhideki-okawaです。
弊社メンバーでチームを組んで7/23に開催されたISUCON12の予選に参加してきました。
今回は、ISUCONに参加する際に行った準備や当日の動きを振り返り、ISUCONに参加した結果どのような学びがあったかを書いていこうと思います。
目次
ISUCONとは
ISUCONとは Iikanjini Speed Up Contest(いい感じにスピードアップコンテスト) の略で、お題となるWebサービスを決められたレギュレーションの中で限界まで高速化を図るチューニングバトルです。
参加メンバー
- 5_21maimai
- 新卒入社7年目
- ニフティ不動産のスマホアプリ開発を担当
- 普段はサーバーに全く触れないため、自身の技術力・知識向上のために参加
- yk-m
- 新卒入社6年目
- ニフティ不動産のバックエンド開発を担当
- Webシステムアンチパターンの学習に活かしたく参加
- hideki-okawa
- 新卒入社4年目
- DFOのバックエンド開発を担当
- AWSのマネージドサービスに頼った開発しか経験がなく、非マネージドのミドルウェアを使った開発環境に慣れたかったため参加
全員がISUCON初参加でした。
結果
最終スコアは3041点で415位でした。初期スコアから中々伸ばすことが出来ず悔しい思いをしました。
とはいえ、学びは非常に多かったので良しとします!!
ここからは、当日までに準備したことや当日の行動を振り返ります。
事前準備
言語選定
Goを選択しました。
参加メンバーに記載の通り様々な背景を持ったメンバーで構成されており、yk-mが慣れているPHPとhideki-okawaが慣れているGoの二択となりました。
最終的には「ISUCONにおいてはGoを利用した参考記事が多い」という理由からGoを選択することにしました。
役割分担
ISUCONでは様々な観点から改善していくことが求められます。そのため役割の分担が重要になると考え、メンバーの持っている背景を考慮して役割の分担を行いました。
- 5_21maimai
- DB担当
- DBスキーマの把握や、インデックスを貼る等のDBチューニングを行う担当
- DB担当
- yk-m
- サーバー担当
- 当日は複数のサーバーが配布されるが全てのリソースが有効に活用されているとは限らない
- 全てのサーバーリソースを有効活用するために設定を変更する担当
- サーバー担当
- hideki-okawa
- 環境構築担当
- 各々のPCでアプリケーションの改善を行うためにローカル開発環境を構築する担当
- 環境構築担当
自分の担当している範囲内で出来ることが無くなった人からアプリケーションの改善を行う方針にしました。
過去問の実施
ISUCON11の予選問題を解き、どのようなアクションを取ればアプリケーションが改善されるかを体感しました。
ISUCONの雰囲気を知ることが出来た良い機会でした。
カンペやスクリプトの用意
当日、スムーズに作業を進めるために各々でカンペやスクリプトの準備を行いました。
カンペ
- 使用するツールのインストール方法
- DBの基本操作(インデックスを貼る等)
- …
スクリプト
- デプロイスクリプト
- ログローテートのスクリプト
- ベンチマークの結果をSlackに送るスクリプト
- …
当日
いざ当日です。
基本的には、ISUCON12の事前講習を参考にタイムテーブルを作成しタスクをこなしていきました。
10時~12時半
午前中は改善を行っていくための土台作りとして以下のタスクを実施しました。
- CFnテンプレートを流してアプリケーションの立ち上げ
- 各メンバーのサーバーへのログイン確認
- ベンチマークの実行
- マニュアルの読み込み
- ブラウザでサービスを触りながら機能の把握
- ツールの導入
- DBスキーマの把握
- アプリケーションの構成や設定ファイルの場所を把握
- GitHubにソースコードのアップロード
ツールについてはアクセスログ集計のためにalp、スロークエリ集計のためにpt-query-digestを利用しました。
また、ベンチマーク中でMySQLのCPU使用率が高いことがわかっていたのでスロークエリの分析を実施しました。
分析を行った結果、visit_historyテーブルのクエリに問題がありそうだと気づきcompetition_idにインデックスを貼ったのですがスコアは上がりませんでした。
13時半~14時半
各メンバー別々のタスクに取り組みました。
ローカル環境構築
「ローカル開発環境があるといいよね」という話をしていたため環境構築を試みました。
しかし、SQLiteの導入にハマってしまい断念しました。
アプリケーションサーバーとDBサーバーの分離
今回は3台のサーバーが提供されていたのですが、1台のサーバーがアプリケーション、MySQL、SQLiteの役割を担っていました。
topコマンドでCPU使用率を確認してみると、MySQLがリソースの多くを占めていたためサーバーを分離することが有効だと考えました。
そこで3台あるうちの1台をMySQL専用サーバーとしました。これでもスコアは上がったようには見えませんでした。
- ISUCON_DB_HOST: 127.0.0.1
+ ISUCON_DB_HOST: isuports-3.t.isucon.dev
また、課題として提供されているサーバー内にSQLite3からMySQLへの移行を手助けするスクリプト(sqlite3-to-sql)を見つけたのもこの時間帯でした。
14時半~18時
このタイミングで、SQLiteのデータをMySQLに移行するか議論を行いました。
以下の3点の理由で移行しないと始まらないという結論になりました。
- MySQLに移行することでJoinが可能になりクエリを実行する回数が減らせるかもしれない
- インターネットで調べるとMySQLに比べてSQLiteはパフォーマンスが出ないと書いてあった
- SQLiteを扱ったことが無くチューニング出来る自信が無かった
ここからは、SQLiteからMySQLへの大移行プロジェクトが開始となりました。
sqlite3-to-sqlを実行すると大量のinsert文が発行され実行を試みます。処理自体は遅かったのですが、18時までには移行が終わりそうだったためそのまま移行を進めることにしました。
また、裏ではアプリケーションの修正を行いtenantDBの参照をSQLiteからMySQLに変更しました。
以下、修正の一例です。
- tenantDB, err := connectToTenantDB(t.ID)
- if err != nil {
- return fmt.Errorf("failed to connectToTenantDB: %w", err)
- }
- defer tenantDB.Close()
- cs := []CompetitionRow{}
- if err := tenantDB.SelectContext(
+ cs := []CompetitionRow{}
+ if err := adminDB.SelectContext(
当日はMySQLに接続しているインスタンス(adminDB)を使いまわしてしまいましたが、以下の修正を行うのが正解だったように思えます。
- tenantDB, err := connectToTenantDB(t.ID)
- if err != nil {
- return fmt.Errorf("failed to connectToTenantDB: %w", err)
- }
- defer tenantDB.Close()
- cs := []CompetitionRow{}
- if err := tenantDB.SelectContext(
+ tenantDB := adminDB
+ cs := []CompetitionRow{}
+ if err := tenantDB.SelectContext(
データの移行が17時半ごろに完了し、アプリケーションについても表示に問題が無く速度についても大きく改善されているように思えました。(目視では)
ただし、一部データの移行に失敗していたようでベンチマークが通らずスコアへの貢献には至りませんでした。
また、全員がこの作業に取り組んでいたため別の改善まで手が回りませんでした。
まとめ
良かったこと
- 過去問の実施
- やることリストを作成し当日実践することができた
- 午前中に関してはかなりスムーズに作業を進めることが出来た
反省点
- ソースコードを読む時間をあまり取らなかった
- ISUCON11の予選問題はDBへのインデックスの設定やサーバーの分割である程度の点数が稼げたためアプリケーションの改善を軽視していた
- ソースコードを読んだ上でSQLiteからMySQLへの移行以外にも改善案を検討するべきだった
- 全員がSQLiteからMySQLに移行することに注力するのではなく一部メンバーが実施するべきだった
感想
参加する前は、MySQLの設定ファイルどこにあるんだ?というレベルで非マネージドなミドルウェアの開発環境には不慣れだったのですがISUCONを通して慣れることが出来ました。
また、今後何らかのパフォーマンスに関する課題にぶつかった際に、改善する方法としてどのような選択肢があるのかを自分の中で考えられるようなったことが非常に大きな収穫だったように思えます。
また、チームメンバーにもコメントを貰いました。
5_21maimai
普段は主にiOSアプリ開発をしているため、DBのチューニングをしたり、計測ツールを使ってサーバーの状態を確認したりなど、いつもはできない経験ができて楽しかったです。
当日は大したことできませんでしたが、当日までに過去問を解いたり解説本を買って復習してみたりと、自分自身の知識を深めることができました。
来年はもう少し戦力になれるように頑張ります。
yk-m
Goのアプリケーションに触れるのははほぼ初めてでした。新しい言語に触れるということはなかなかないので、いい刺激になったと思います。競技としてとても楽しい上にパフォーマンスチューニングについても学べる、とても素敵なイベントでした。
最後に
今回は「脱・お茶汲み係」というチーム名で参加してきました。メンバーの一人が「お茶汲みくらいしか出来ることが無いけど」と話していたところから付けたのですが、当日は各メンバーがそれぞれの領域で貢献しておりました。
ISUCONでは1~3人の少人数で多くの作業を実施する必要があります。そのために役割分担を行い、それぞれの役割を責任を持って全うする必要があります。
責任を持つということは非常に怖いものですが、同時に良い経験が出来たと感じています。
ぜひ来年も参加したいと思います。
ISUCON運営の皆様お疲れさまでした。そしてありがとうございました!
掲載内容は、記事執筆時点の情報をもとにしています。