投稿日: 2022-07-03
ISUCON11予選で練習をした記録です。ISUCON11予選は、参加したものの初期スコアを超えられなかった苦い記憶があります。
matsuu/vagrant-isuconからVagrantfileをお借りして、vagrant up
して環境を作りました。vagrant ssh-config
でサーバーにSSHする設定が見れるので、~/.ssh/config
にコピペしてVSCodeでRemote SSHして作業しました。
isucon11-qualify/isucondition.mdにあります。用語や用語同士の関係を早めに理解しておくとうれしいと思います。ISUとかコンディションとかトレンドなどの用語が色々なところで出てくるからです。
ユーザーの行動の傾向とかも書かれてあるので、ベンチマーカーの挙動を推測するときにも役に立ちそうでした。
Nginxのアクセスログをltsvに変更します。
アクセスログを空にする→ベンチを実行する→アクセスログ集計までのコマンドをMakeで作りました。alpの集計コマンドは解説からお借りしました。重要なのは正規表現を使ってまとめることと、SUMで降順ソートすることです。
GoだとDBにボトルネックがあって初手インデックスっぽいのですが、Node.jsだとappサーバーが重いのでまずはそこを改善しようと思いました。appのどこが重いのかは分からないのですが、調べた感じ一番リクエストが飛んでるところをBulk Insertにするといいらしいのでそれを試してみました。
alpだと50000件くらいリクエストが飛んできていることが分かります。確かにここを改善するのが良さそうです。
+-------+--------+------------------------------+-------+-------+----------+-------+-------+
| COUNT | METHOD | URI | MIN | MAX | SUM | AVG | P99 |
+-------+--------+------------------------------+-------+-------+----------+-------+-------+
| 57096 | POST | /api/condition/[-a-z0-9]+ | 0.004 | 0.532 | 2110.062 | 0.037 | 0.108 |
| 224 | GET | /api/isu/[-a-z0-9]+ | 0.004 | 1.064 | 174.031 | 0.777 | 1.013 |
| 180 | GET | /api/isu | 0.032 | 1.092 | 164.891 | 0.916 | 1.092 |
| 105 | POST | /api/isu | 0.004 | 1.008 | 67.611 | 0.644 | 1.005 |
| 68 | POST | /api/auth | 0.020 | 1.032 | 36.514 | 0.537 | 1.032 |
| 78 | GET | /api/isu/.+/icon | 0.004 | 0.804 | 16.620 | 0.213 | 0.804 |
| 31 | GET | /api/condition/[-a-z0-9]+ | 0.660 | 1.009 | 4.131 | 0.133 | 1.009 |
| 10 | GET | /api/trend | 0.032 | 1.000 | 2.740 | 0.274 | 1.000 |
| 22 | GET | /api/isu/.+/graph | 0.148 | 0.800 | 2.125 | 0.097 | 0.800 |
| 49 | GET | /assets/vendor.ee7444dd.js | 0.004 | 0.184 | 1.112 | 0.023 | 0.184 |
| 49 | GET | /assets/index.23dac98b.js | 0.004 | 0.052 | 0.452 | 0.009 | 0.052 |
| 49 | GET | /assets/favicon.d0f5f504.svg | 0.004 | 0.052 | 0.440 | 0.009 | 0.052 |
| 49 | GET | /assets/index.144d8ca8.css | 0.004 | 0.056 | 0.428 | 0.009 | 0.056 |
| 27 | GET | / | 0.004 | 0.040 | 0.312 | 0.012 | 0.040 |
| 49 | GET | /assets/logo_white.svg | 0.012 | 0.048 | 0.228 | 0.005 | 0.048 |
| 12 | GET | /api/user/me | 0.016 | 0.024 | 0.188 | 0.016 | 0.024 |
| 12 | GET | /assets/logo_orange.svg | 0.008 | 0.048 | 0.160 | 0.013 | 0.048 |
| 1 | POST | /initialize | 0.144 | 0.144 | 0.144 | 0.144 | 0.144 |
| 6 | POST | /api/signout | 0.020 | 0.020 | 0.032 | 0.005 | 0.020 |
| 18 | GET | /isu/.+/condition | 0.000 | 0.004 | 0.012 | 0.001 | 0.004 |
| 6 | GET | /isu/.+ | 0.000 | 0.004 | 0.012 | 0.002 | 0.004 |
| 6 | GET | /isu/.+/graph | 0.000 | 0.004 | 0.004 | 0.001 | 0.004 |
| 3 | GET | /register | 0.000 | 0.004 | 0.004 | 0.001 | 0.004 |
+-------+--------+------------------------------+-------+-------+----------+-------+-------+
Bulk Insertにしたところ、スコアの減点は減りましたが、加点は増えませんでした。
Before:
11:28:23.071980 score: 959(1000 - 41) : pass
11:28:23.073318 deduction: 0 / timeout: 416
After:
22:09:45.169834 score: 997(1000 - 3) : pass
22:09:45.169856 deduction: 0 / timeout: 37
修正が反映されているか自身がなかったので、適当なエンドポイントを作って確かめました。Node.jsの場合はtscでコンパイルして、systemdで再起動する必要がありました。
打つ手がなくなったので公式解説を見ながらインデックスを貼るのをやってみました。appサーバーが重いのでそれはそうという感じですが、スコアは伸びませんでした。
難しいですが、スコアが伸びることを考えると楽しいです。まだボトルネックと改善方法の対応付けができていないので、色々試してみようと思います。目標は1万点!