tekiehei2317's blog

ISUCON練習記録(Part 1)

投稿日: 2022-07-03

ISUCON11予選で練習をした記録です。ISUCON11予選は、参加したものの初期スコアを超えられなかった苦い記憶があります。

やったこと

  • Vagrantでローカル環境を作成
  • アプリケーションマニュアルを読む
  • alpでの計測
  • Bulk Insert対応
  • インデックスを貼ってみる

Vagrantでローカル環境を作成

matsuu/vagrant-isuconからVagrantfileをお借りして、vagrant upして環境を作りました。vagrant ssh-configでサーバーにSSHする設定が見れるので、~/.ssh/configにコピペしてVSCodeでRemote SSHして作業しました。

アプリケーションマニュアルを読む

isucon11-qualify/isucondition.mdにあります。用語や用語同士の関係を早めに理解しておくとうれしいと思います。ISUとかコンディションとかトレンドなどの用語が色々なところで出てくるからです。

ユーザーの行動の傾向とかも書かれてあるので、ベンチマーカーの挙動を推測するときにも役に立ちそうでした。

alpでの計測

Nginxのアクセスログをltsvに変更します。

アクセスログを空にする→ベンチを実行する→アクセスログ集計までのコマンドをMakeで作りました。alpの集計コマンドは解説からお借りしました。重要なのは正規表現を使ってまとめることと、SUMで降順ソートすることです。

Bulk Insert対応

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サーバーが重いのでそれはそうという感じですが、スコアは伸びませんでした。

結果

  • Goはインデックスを貼るだけでスコアが5000点になった
  • Node.jsはBulk Insertをすると減点が減ったが、加点は伸びなかった
    • -41点→-3点

学んだこと

  • topを使ってapp、web、dbのどこが重いかを確認する
    • alpを使って重いエンドポイントを見る。SUMが大きいところから改善する。
  • アプリケーションマニュアルを読むのが大事(ドメイン知識重要)
    • 去年参加していたけど、今読んで初めて気づいたことがかなりあった
  • 言語によってボトルネックが違うことがあるらしい

次やること

  • AWSでやってみる
    • なるべく本番に近い環境でやったほうがいい気がしました
  • Node.jsのappサーバーの負荷を下げる方法を考える
    • プロファイリングをとると良さそうな気がします
  • ISUCON11予選の解説記事を読む(Node.js)
  • ISUCONの本を読む

感想

難しいですが、スコアが伸びることを考えると楽しいです。まだボトルネックと改善方法の対応付けができていないので、色々試してみようと思います。目標は1万点!

参考