チーム(´・ω・`)です
タイトルにもありますが、先日参加させていただいた「ISUCON14」において、PHP言語で1位になることができました👏
全体では17位、スコアは31,002でした
やったこと
最終的なサーバの構成といたしましては
- アプリケーションA(ロードバランス+アプリ)
- アプリケーションB(Macher+アプリ)
- MySQL
の3台構成となりました
ベンチマーカーからのリクエストをアプリケーションAのnginxで受け、1:1でAとBに振り分けるようにしました
MacherはアプリケーションBの内部でcurlで実行し続けました
ソースコード
https://github.com/KaNiShi/isucon14
コード面で行ったこと
コード面では
- 各テーブルにインデックスを付与する
- chair_locations を利用しないようにする
- GetMatchingの処理を改善する
といったことを行いました
各テーブルにインデックスを付与する
こちらはSlowQueryを見たり、プログラム全体を”SELECT”で検索を行い必要そうなインデックスを追加しました
適切な追加をする必要がありますが、必要そうなもの全てのパターンで追加していきました
chair_locations を利用しないようにする
chair_locations は移動したすべての座標の情報が残っており、合計移動距離を計算することに利用されていましたが、それ以外特に使われていなさそうだったため、
代わりに chair_distances というテーブルを作成し、そこに最後の座標とトータルの距離を残すようにしました
GetMatchingの処理を改善する
ここが一番得点に響きました
Macherの処理を高速化することで得点が伸ばせそうな雰囲気があったため、1度に処理する量や間隔を調整しました
また、 ST_Distance を用いて移動距離を算出し椅子のスピードと合わせスコア付けをしできるだけ最適な椅子が割り当たるようにしました
ベンチマーカーなどから大量に叩かれるといったことがないため、N+1などに関しましてはそれほど気にせず実装しました
競技中はパッといいアイデアが思い浮かばずこのような実装をしましたが、競技後に冷静に考えてみますと、ST_Distanceは使わずプログラム側で計算する方が良かったんじゃないかと思いました
インフラ面で行ったこと
インフラ面では
- xdebug.mode を “off” にする
- opcache.validate_timestamps を “off” にする
- MySQLの innodb_flush_log_at_trx_commit を “0” にする
- MySQLのバイナリログを無効にする
といったことを行いました
xdebug.mode を “off” にする
XDebugが導入されており、”develop” モードで動作していましたのでこちらを “off” にして黙らせました
後から考えますと、拡張機能自体を無効にしてもよかったかもしれないです…
opcache.validate_timestamps を “off” にする
スクリプトの更新確認は不要だったため、 “off” としました
offにするとプログラム更新後にphp-fpmを再起動させる必要がありますので、Makefileで git pull と php-fpmの再起動を行えるようにしました
MySQLの innodb_flush_log_at_trx_commit を “0” にする
耐障害性を犠牲に書き込み性能をあげます
MySQLのバイナリログを無効にする
バイナリログは不要なのでoffとしました
感想
チームの目標としましてはやはり「全体1位になる」ことだったので、若干悔しい点もありますが、PHP言語では1位を取ることができかなり嬉しく思いました
これまでのisuconはボトルネックを解消する事が全てでしたが、ビジネスロジックを考える必要がある問題だったため非常に新鮮で楽しかったです
PHP自体やComposer部分の処理などを早くしたとしてもビジネスロジックがボトルネックで点数が逆に下がってしまい、途中 39,000点までいったのに最終スコアが31,000点になってしまい原因も掴めず終わってしまいました(´・ω・`)
競技終了後まだまだやれることが多くあることがわかり、まだまだ実力不足なんだなと感じました
また次回がありましたら参加したいなと思っております
謝辞
ISUCON運営の皆さん楽しい問題を出していただき、本当にありがとうございました