この記事は、CYBOZU SUMMER BLOG FES '24 (Garoon Stage) DAY 2の記事です。
サイボウズ Garoon開発 Nozomiチームのぱくとまです。
今年もGaroonチームに新メンバーが配属される季節がやってきました🎉
本記事では、Garoonの性能改善を担うNozomiチームで、チーム体験の際に実施したISUCON過去問の素振り会の模様をお届けします📹️
3行まとめ
現在、Garoonチーム配属の新メンバーに、新人研修の一環で各チームを体験してもらっています。
Nozomiチームでは業務体験の息抜きとして、ISUCONの過去問に挑戦することにしました。
全員がほぼ初めての挑戦で、見事コテンパンにやられました。
ISUCONについて
ISUCONとは、「LINEヤフー株式会社が運営窓口となって開催している、お題となるWebサービスを決められたレギュレーションの中で限界まで高速化を図るチューニングバトル」です。(公式サイトより)
「ISUCON」は、LINEヤフー株式会社の商標または登録商標です。
チーム体験
Garoonを開発しているGaroon開発チームでは、新人配属となったメンバーに4つのサブチームを体験してもらうチーム体験を毎年実施しています。
Garoon開発チームのサブチームについては、以下の記事に詳しく書かれています!
そして、Garoonの性能改善を担当するNozomiチームのチーム体験では、業務体験の息抜きとしてISUCONの過去問にモブプログラミングで取り組みました。
環境構築
大会の過去問自体は公式GitHubに公開されていますが、今回はISUNARABEというサービスを利用して環境構築をしました。
過去に社内有志で実施された「ISUCON素振り会」という会の際に生産性向上チームのuta8aさんが準備してくださったドキュメントを参考にして進めました。ありがとうございます!
挑戦ログ
挑戦条件
- ISUCON13の過去問をAWS上にデプロイ
- 予定時間:1時間
- 実際の時間:2時間
準備の時点で時間が足りなくなったので延長しました😭
サーバー側でsshキーを登録
メンバー全員がsshで繋げるように公開鍵を各サーバーに登録しました。
https://github.com/{user1,user2,user3}.keys >> ~/.ssh/authorized_keys
GitHubから簡単に公開鍵を取ってこれるのは知りませんでした。
コマンド一発で公開鍵の設定が出来て便利なので、今後積極的に使いたいです。
クライアント側でsshのconfigを書く
Host isu1 HostName {IPアドレス} User isucon ServerAliveInterval 60 (他のホストも同様)
ServerAliveInterval 60
はSSHのタイムアウトを避けるための設定です。
/etc/hosts
の設定
マニュアルを参考に、/etc/hosts
の設定をしました。
社内LANで実施していたメンバーがProxyの影響か通信出来なかったことと、動作確認には追加で複数のエントリの登録が必要になるので、もしかするとローカルにDNSサーバーを立てたほうがよいかもしれません。
ローカルDNSサーバーを使って社内LANから接続できるようになるかは分かりませんが、サブドメインをワイルドカードで書けるようにはなるはずです。
実装をPHPに切り替え
マニュアルを参考に、実装をPHPのものに切り替えました。
切り替えた瞬間にベンチマーカーのスコアが3000近くから1366まで落ちました。不利……!
今回はアプリやDB側を見ることを優先したのでPHPの設定側は見れていないのですが、もしかするとphp.ini
側の設定を詰めることもできたのかもしれません。
設定ファイルについては、ちゃんと参加する方は各々でテンプレートを用意しているみたいです。
計測の準備
ISUCONでは一般的にalp, pt-query-digest, pprofを使って計測をするようです。
alpはnginxのアクセスログ解析、pt-query-digestはMySQLのログ解析、pprofはGolangのプロファイリングツールです。
実運用ではGrafana + LokiやElastic Stack、New Relic、Datadogなんかを使うことが多いと思うのですが、環境構築の重さを嫌ってCLIツールを使っているみたいです。個人的にはGUIツールに慣れていたので読むのが大変でしたが、AWKとかに慣れているチームメンバーは使いやすそうでした。
私たちはPHPで作業を進めていたので、プロファイリングはXdebugで実施しました。なお、参考実装には最初からXdebugもComposerも設定されているのですが、私たちはそれに気が付かず、「Xdebugは入れる時間がないので一旦nginxとMySQLのログだけ見ますか~」と進めていました。
計測
ベンチマーカーを動かして一通りログを取りました。
この時点で1時間30分が経過しています😢
性能改善
残り時間は30分と限られていますが、出来るところまで触ってみることにしました💪
まず、alpでアクセスログを見たところstatistics
というエンドポイントが何度も呼ばれていて時間がかかっていたので、ここを改善しようと決めました。
アプリの中身を見るとn+1のようなものがありましたが、一旦そこは置いてDBから触りました。
DBのクエリを見ると複数のテーブルをユーザーのPKを使って引いていたので、外部キー制約を付ければインデックスも張られるし一石二鳥では、という話になり外部キー制約を付けました。
ところが、外部キー制約を付けた状態でベンチマーカーを回したところ整合性チェックで落ち、DBを見るとデータが足りていませんでした。どうも初期データ投入時に外部キー制約を満たさないことがあるようでした。仕方がないので外部キー制約を全て外し、振り出しに戻ります。
競技といえど素直なデータが入ってくるわけではないようなので、SQLの制約は付けないほうが良いみたいです。
その後、インデックスを貼ったりN+1を解消したりした結果、エンドポイントの応答は速くなったものの予想に反してベンチマークの点数は上がりませんでした。
後からドキュメントを読んだ結果、ユーザーの特定の操作の回数が点数になっているようで、そこに直結する部分を高速化出来ないとベンチマークの点数は上がらないようです。
どうも、性能改善に着手する前にアプリを触ったり時系列データを取ったりして点数に直結する部分を洗い出す必要がありそうです。
ここで30分が経過し、成果が上がらないまま終了となりました😭
感想
Nozomiチームのメンバー2人とチーム体験メンバー1人の3人で挑みましたが、結果的には全くスコアを上げられない結果になりました。
一方で、チーム体験メンバーからの反応は上々で、先輩がすごかったとの感想をいただいたのでイベントとしては成功だったかなと思います。
私としても、一度過去問をやってみることでISUCONの難しさや楽しさを感じることができました。本番にもぜひ準備して出てみたいなと思います。
目標は今年のISUCON予選出場です!(応募的な意味で)