なまえは まだ ない

思いついたことをアウトプットします

ISUCON14延長戦の記録⑨ N+1問題の解消とクロージング

ISUCON14の延長戦をやってます

以下の記事の続きです。

furusax0621.hatenablog.com

前回は2つめの通知エンドポイントレスポンスをキャッシュし、ついに本戦当時の6位相当までスコアを伸ばすことができました。 今回はユーザーの通知エンドポイントの中で気になった実装の改善、最後のチューニングに触れていきます。

なお、最終的なコードは以下のリポジトリで公開しています。

github.com

椅子の評価情報を簡単に取得する

ユーザーの通知エンドポイントのレスポンスには椅子の評価情報が含まれています。 内容としてはこれまでに完了したライドの数と、これまでに受けた評価の平均値です。

github.com

初期実装は以下リンクのとおりで、椅子にこれまで割り当てられたライドの一覧を取得したあと、ライド毎に最新のステータスを取得するという、非常にわかりやすいN+1問題になっています。 https://github.com/furusax0621/isucon14-extend/blob/e5834de96efcf5e27cb7f4189951ee0f6fa8eb0d/webapp/go/app_handlers.go#L766-L817

これまでの実装により、ライドとその最新のステータスは単純なJOINができるようになりました。ライド数と評価の合計値も簡単な集計クエリで取得可能です。レスポンスに必要な平均値は、クエリで合計値を取得後にアプリケーション側で計算しました。

SELECT
    COUNT(r.evaluation) AS total_rides_count,
    SUM(r.evaluation) AS total_evaluation 
FROM rides AS r
JOIN ride_latest_statuses AS rl
    ON r.id = rl.ride_id
WHERE
    rl.status = 'COMPLETED'
    AND r.chair_id = ?

競技終了前の最終チューニング

スコアを伸ばすための最後の一押しとして、サーバーで記録している各種ログを無効化します。 ログ出力は多少なりとも計算コストやディスクへの書き込みコストが発生するため、これらを無効化することでパフォーマンス改善が見込めます。

アプリケーションコードからpproteinエージェントを削除する

計測用に導入したpproteinエージェントの実装を削除します。Pull Requestを作るのも面倒だったので、mainブランチに直プッシュしました。以下のコミットです。

github.com

MySQLのスロークエリログを無効化する

template-isucon-recipeで追加したスロークエリログの設定を削除します。設定は独立したファイルになっているため、そのファイルをそのまま削除すればOKです。

sudo rm -f /etc/mysql/mysql.conf.d/slow-query-log.cnf

MySQLのバイナリログを無効化する

MySQL 8.0ではデフォルトでバイナリログが有効になっており、この書き込みがパフォーマンスに影響を与えます。これも無効化しておくことでパフォーマンス改善が見込めます。

/etc/mysql/my.cnf などに以下の設定を追加しましょう。

[mysqld]
disbale-log-bin

Nginxのアクセスログを無効化する

アクセスログをalpで解析するための設定を削除しつつ、Nginx全体でアクセスログを無効化します。alp用の設定はtemplate-isucon-recipeによって反映されているので、ファイルを削除すればOKです。

sudo rm -f /etc/nginx/conf.d/alp.conf

アクセスログの無効化は /etc/nginx/nginx.conf を修正し、アクセスログの設定をしている箇所を探して以下のように記述しましょう。

access_log off;

終結

ここまでの変更をすべて反映し、何度かベンチマーカーを動かし、最終的に51,873点まで到達しました。本戦当時のスコア換算だと4位相当です。頑張ったけど1位には届かなかった……残念!

(宣言どおり、ちゃんとまとめ記事書いたぞ。えらい)

まとめ

今回、運営側の御厚意で得た延長戦のチャンスを使って、改めて問題を解いてみました。新しい発見や学びがあり、非常に充実したチャレンジでした。運営の皆さま、本当にありがとうございました。

一方で、最終的に3台目のサーバーを使えなかったこと、SSEなど実装しきれずに諦めたことなど、課題もたくさんあります。現時点でトップスコアは50万点を超えていることからも、まだまだ改善の余地はあるようです。まとまった時間があるときに、改めて考えたり、他の参加者の解法を解読したりしてみようと思います。