isucon練習記 isucon11(予選) 2度目
環境構築
今回はEIPも割り当てた
code:いつもの
$ sudo hostnamectl set-hostname isu1
$ sudo mkdir -p /home/isucon/.ssh &&\
sudo cp ~/.ssh/authorized_keys /home/isucon/.ssh &&\
sudo chown -R isucon:isucon /home/isucon/.ssh
/etc/hosts の書き換え
{isu1のIP} isucondition-1.t.isucon.dev
マニュアル
チューニング
ベンチ回す
セキュリティグループで443, 4999番を開けておく必要あり
./bench -all-addresses {isu1のIP} -target {isu1のIP}:443 -tls -jia-service-url http://{benchのIP}:4999
4999番はlsofした感じ使われてないので、ベンチマーク実行時にjia-service-urlにサービスが立つ?
初期スコアは1882
nodejsに実装変える
スコア1228
スロークエリが出ない
general_logなる設定があるらしい。知らなかった...
プロファイリング開始
負荷はnodeが80~100%、mariadbが50%~100%くらい
ptで圧倒的に専有してるクエリがあるのでインデックス貼ってみる
# 1 0x8155B89FFD74A9D523D19AC... 228.2155 66.3% 3575 0.0638 0.05 SELECT isu_condition
INDEX jia_isu_uuid_idx(jia_isu_uuid),
score: 3378(3386 - 8)
kataribeを見るとPOST /api/conditionへのリクエストが圧倒的に多い
多すぎてdropProbabilityという変数で少し弾いてるっぽい
0.6にしてみる → スコア激減
リクエストの内容をconsole.logしてみる
リクエストは複数同時に来るけど、全部ループでINSERTしてるので最新のものだけで良さそう
score: 9518(9520 - 2)
dropProbabilityを0.6にしてみる → スコア微減
マニュアルのユーザは一覧中の、最新コンディションに変化がない ISU には興味を持ちません。から送られてきたコンディションが前と同じ場合は弾いておkと予想して弾いてみる
ログ見た感じそこそこの頻度で同じコンディションが来てる
score: 8964 ほぼ変わらず
dropProbabilityを0.6にしてみる → スコア微減
またptを見ると二番目に GET /api/trendのクエリが来てる
コンディションを取得するクエリが呼ばれているが実際は最新のものだけで良さそう
あとN+1にもなっている
解消してみる
score: 2156
ただし速度は上がって叩かれる回数が143回から1024回になってた
スコアは下がったけど、信じてそのままにしてみる
トップページのアクセスが増えたのでgzip有効にしてみる
score: 1635(1664 - 29)
そろそろDBの負荷は落ち着いてきてそう
htop見た感じDBが20%前後、appが100%
3台構成にしてみる
isu1 app、isu2 app(/api/condition)、isu3 db
score: 7984
/api/trendへの対処をrevertしてみる
score: 14189(14196 - 7)
自分のブログを見返したらPOST /api/conditionはバルクインサートすべきだったらしい
インサートを1件にする対処をrevert score: 15311
バルクインサートしてみる score: 16294(16296 - 2)
スキップもやめる score: 19917(19920 - 3)
dropProbability 0.6 スコア変わらず
マニュアル見返したらPOST /api/conditionへの反映は遅延してもいいらしい
登録したいデータを文字列で保存しておいて、setIntervalで800ミリ秒ごとにINSERTしてみる(こんなことしていいのか?)
ベンチは通るがスコアは変わらず score: 20882(20884 - 2)
何していいか分からなくなってきた
ptを見てインデックスを貼る
INDEX jia_isu_uuid_timestamp_idx(jia_isu_uuid, timestamp)
score: 22085(22088 - 3)
静的ファイルをnginxから配信 score: 23294(23296 - 2)
解説を読む
公式記事を読む
/api/trendにLIMIT 1をつける
score: 4972 なぜか分からないけど/api/trendを改善するとめちゃくちゃスコアが落ちる
ユーザーが増えるからっぽい
condition_levelの事前計算
初期データに影響を及ぼさずどうやってテーブル変更するんだと思ったら、初期データを読んだ後にALTERしてた盲点
score: 28610
score: 30730
iconをDBから剥がす
/api/trendをキャッシュ
1秒キャッシュ score: 45016(45026 - 10)
10秒キャッシュ score: 63589(63592 - 3)
学び
初期データに影響を与えるようなDBスキーマの変更は、用意されたsqlを読み込み終わった後にALTERする
認証もなく、最新のDB結果が必ずしも必要でないエンドポイントはキャッシュを試みる