ISUCON14
code:text
## やったこと
10:20 github 設定 done
10:26 DataGrip 設定 done
10:37 slow quey log on
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
`
# Here you can see queries with especially long duration
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 1
`
sudo systemctl restart mysql.service
11:15
alp設定done
11:45
notificationsを叩きすぎなのでretry間隔を30ms -> 200msにしてみる
11:49
何も変わらないと思ったら、goのサービスを停止してなかったぽい.. もう一度
sudo systemctl disable --now isuride-go.service
sudo systemctl enable isuride-ruby.service
retry
12:13
外部キーが必要そうなところにindexをはる
nearby-chairsの下が200ms以上かかっていたので
SELECT * FROM rides WHERE chair_id = ? ORDER BY created_at DESC LIMIT 1
12:18
chairsのaccess_tokenにインデックス
POST /api/chair/coordinateを見る
SELECT * FROM rides WHERE chair_id = ? ORDER BY created_at DESC LIMIT 1 にインデックス貼る
12:36
やはりnotificationに時間がかかりすぎなので1sにすべて調整
12:47
/api/owner/chair がリクエスト数は少ないが2位に。
クエリ改善を試みるが苦戦... 結局owner_idで絞るだけはやることに
mysqldのCPU使用率が70%ぐらいに下がった
13:30
マッチされるまでの時間に不満があるユーザーが多かったので、ポーリングタイムを変更したらぐっと伸びた
13:33
マッチされた椅子が乗車地点までに掛かる時間を直していく
/api/internal/matchingを改良する
`
# MEMO: 一旦最も待たせているリクエストに適当な空いている椅子マッチさせる実装とする。おそらくもっといい方法があるはず…
ride = db.query('SELECT * FROM rides WHERE chair_id IS NULL ORDER BY created_at LIMIT 1').first
`
14:36
近い車から配車するようにした
不満が90%+から40~70%になった
速度も考慮するとなおよさそう
14:24
speedも考慮してマッチングするようにした
14:48
まってるrides全部まとめてマッチングさせる
25.4%のライドは椅子がマッチされるまでの時間、48.7%のライドはマッチされた椅子が乗車地点までに掛かる時間、90.7%のライドは椅子の実移動時間に不満がありました
とのこと。
乗車後の移動も含めて最も速いisuを選ぶようにしてみる
14:55
移動距離も含めてisuをマッチングするようにしたがあまり変わらず。ボトルネックがここじゃない感
/api/app/nearby-chairs が2位なので見てみるか
みたがあまり変わらず
/api/chair/coordinate をさばけないとやはり厳しいか
16:18
複数台構成に挑戦するも、ベンチマーカーがこけるようになってしまう。
時間を溶かした...
16:53
nearbyのN+1を潰すもベンチマーカーがfailする
もう時間がないので細かいクエリ改善で終わろう
sudo mysqldumpslow -s t -t 5
## マシン調査
processors 2個
grep processor /proc/cpuinfo
processor : 0
processor : 1
メモリ4G swapなし
free -m
total used free shared buff/cache available
Mem: 3794 982 2193 2 867 2812
Swap: 0 0 0
## プロファイル
`
show variables like 'slow%';
+-------------------+---------------------------------------+
|Variable_name |Value |
+-------------------+---------------------------------------+
|slow_launch_time |2 |
|slow_query_log |OFF |
|slow_query_log_file|/var/lib/mysql/ip-192-168-0-11-slow.log|
+-------------------+---------------------------------------+
show variables like 'long%';
+---------------+---------+
|Variable_name |Value |
+---------------+---------+
|long_query_time|10.000000|
+---------------+---------+
`
slow log
GET /api/owner/chairs の中のこれだけめちゃ遅い
`
Reading mysql slow query log from /var/log/mysql/mysql-slow.log
Count: 55 Time=4.72s (259s) Lock=0.00s (0s) Rows=4.0 (221), isuconisucon@localhost SELECT id,
owner_id,
name,
access_token,
model,
is_active,
created_at,
updated_at,
IFNULL(total_distance, N) AS total_distance,
total_distance_updated_at
FROM chairs
LEFT JOIN (SELECT chair_id,
SUM(IFNULL(distance, N)) AS total_distance,
MAX(created_at) AS total_distance_updated_at
FROM (SELECT chair_id,
created_at,
ABS(latitude - LAG(latitude) OVER (PARTITION BY chair_id ORDER BY created_at)) +
ABS(longitude - LAG(longitude) OVER (PARTITION BY chair_id ORDER BY created_at)) AS distance
FROM chair_locations) tmp
GROUP BY chair_id) distance_table ON distance_table.chair_id = chairs.id
WHERE owner_id = 'S'
`
`
+--+-----------+---------------+----------+----+-------------+-----------+-------+-----------------+-----+--------+---------------+
|id|select_type|table |partitions|type|possible_keys|key |key_len|ref |rows |filtered|Extra |
+--+-----------+---------------+----------+----+-------------+-----------+-------+-----------------+-----+--------+---------------+
|1 |PRIMARY |chairs |null |ALL |null |null |null |null |521 |10 |Using where |
|1 |PRIMARY |<derived2> |null |ref |<auto_key0> |<auto_key0>|106 |isuride.chairs.id|45 |100 |null |
|2 |DERIVED |<derived3> |null |ALL |null |null |null |null |23533|100 |Using temporary|
|3 |DERIVED |chair_locations|null |ALL |null |null |null |null |23533|100 |Using filesort |
+--+-----------+---------------+----------+----+-------------+-----------+-------+-----------------+-----+--------+---------------+
`
:heavy_check_mark: chair_locationsにindex追加
`
Count: 98 Time=0.28s (27s) Lock=0.00s (0s) Rows=1.0 (98), isuconisucon@localhost SELECT * FROM chair_locations WHERE chair_id = 'S' ORDER BY created_at DESC LIMIT N
Count: 22 Time=0.33s (7s) Lock=0.00s (0s) Rows=1.0 (22), isuconisucon@localhost SELECT * FROM chairs WHERE access_token = 'S'
Count: 10 Time=0.48s (4s) Lock=0.00s (0s) Rows=1.0 (10), isuconisucon@localhost SELECT * FROM users WHERE access_token = 'S'
Count: 5 Time=0.22s (1s) Lock=0.00s (0s) Rows=1.0 (5), isuconisucon@localhost SELECT COUNT(*) = N FROM (SELECT COUNT(chair_sent_at) = N AS completed FROM ride_statuses WHERE ride_id IN (SELECT id FROM rides WHERE chair_id = 'S') GROUP BY ride_id) is_completed WHERE completed = FALSE
`
:heavy_check_mark: chairsのほうはindex追加
`
Count: 19 Time=0.38s (7s) Lock=0.00s (0s) Rows=1.0 (19), isuconisucon@localhost SELECT * FROM chairs WHERE access_token = 'S'
Count: 5 Time=0.33s (1s) Lock=0.00s (0s) Rows=1.0 (5), isuconisucon@localhost SELECT * FROM users WHERE access_token = 'S'
`
## コマンド
ベンチマーク前
git pull && sudo rm /var/log/mysql/mysql-slow.log && sudo rm /var/log/nginx/access.log && sudo systemctl restart isuride-ruby.service mysql.service nginx.service
ruby起動
sudo systemctl enable --now isuride-ruby.service
Ruby再起動
sudo systemctl restart isuride-ruby.service
mysqld編集
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
sudo systemctl restart mysql.service
mysqldumpsloq
sudo mysqldumpslow -s t /var/log/mysql/mysql-slow.log
nginx編集
sudo vim /etc/nginx/nginx.conf
sudo systemctl reload nginx
sudo cat /var/log/nginx/access.log | grep "/api/" | alp ltsv -m"/api/app/rides/A-Z0-9+/evaluation","/api/chair/rides/A-Z0-9+/status" --sort sum -r マッチングのポーリング変更
vim /home/isucon/env.sh
sudo systemctl restart isuride-matcher.service
puma設定をsystemctlで変更
sudo vim /etc/systemd/system/isuride-ruby.service
sudo systemctl daemon-reload
sudo systemctl restart isuride-ruby.service