Nginxの変更を適用させるとスコアの変動はありませんでしたが、kataribeの結果がガラッと変わり GET / が支配的であることが分かってきました。
Top 20 Sort By Total
Count Total Mean Stddev Min ... Max 2xx 3xx 4xx 5xx Request
175 69.573 0.397560 0.374569 0.003 ... 1.362 175 0 0 0 GET / HTTP/1.1
15 8.977 0.598467 0.403106 0.005 ... 1.237 0 15 0 0 POST /logout HTTP/1.1
18 6.993 0.388500 0.294109 0.032 ... 1.308 18 0 0 0 GET /noriaki HTTP/1.1
6 6.788 1.131333 0.318667 0.633 ... 1.620 6 0 0 0 GET /search?q=travel HTTP/1.1
benchmark中のCPU負荷がそこまで高くなかったのでおもむろにunicornのworker_processを1→2に上げるとスコアが1500→1700に上がり、しっかりとDBのCPU負荷がボトルネックになっていることが分かりました。なので、kataribeで得た情報と組み合わせ GET / で実行しているクエリを精査しようね、という話になりました。
Team-B: @hayaokimura, @unblee
GET / ではログインしているユーザーのフォロワーのツイートを50件返すという仕様でした。 ですが、実行されているクエリはSELECT * FROM tweets ORDER BY created_at DESC と全ツイートを取得し、アプリケーション側でフォロワー以外のツイートを弾くという無駄な実装になっていました。全ツイートは10万件あったので実際に必要なデータの2000倍取得していたことになります。無駄すぎる
kataribeをチェックするとGET / が速くなったことが確認でき、GET / , GET /search , GET /hashtag が同程度に遅いことが分かったのでこの3つのendpointの高速化を考えることにしました。
Top 20 Sort By Total
Count Total Mean Stddev Min ... Max 2xx 3xx 4xx 5xx Request
85 63.131 0.742718 0.235661 0.491 ... 1.534 85 0 0 0 GET /hashtag/*
85 62.244 0.732282 0.213678 0.499 ... 1.579 85 0 0 0 GET /search?q=*
421 61.022 0.144945 0.173544 0.002 ... 0.969 421 0 0 0 GET / HTTP/1.1
210 18.781 0.089433 0.075525 0.025 ... 0.448 210 0 0 0 GET /?append=1&until=*
GET / はN+1問題が発生していたのでこれを解決すると3800→3941に。 スコアとしてはあまり変わらなかったけど、平均レスポンス速度が1.4倍と確実に速くなっているのでどんどんmergeをしていきます。
# Before
Count Total Mean Stddev Min ... Max 2xx 3xx 4xx 5xx Request
421 61.022 0.144945 0.173544 0.002 ... 0.969 421 0 0 0 GET / HTTP/1.1
# After
Count Total Mean Stddev Min ... Max 2xx 3xx 4xx 5xx Request
435 44.218 0.101651 0.135292 0.003 ... 0.610 435 0 0 0 GET / HTTP/1.1
GET /search , GET /hashtag は内部的に同じメソッドを呼んでいたため、1ヶ所修正すれば両方のendpointの高速化ができることが発覚。修正をしてbenchmarkを実行すると3941→13311とスコアが跳ね上がりました。