サイバーエージェントのBackend Tuning Competitionに参加しました

6月の7、8日にサイバーエージェントのBackend Tuning Competitionというインターンに参加してきました。

形式としては個人戦のISUCONのようなもので、2日間にわたってサーバサイドの実装やDBなどをチューニングしてスコアを競うというものです。

そこで自分がやったことなどを書いておこうと思います。

1日目

言語の選択

最初にプログラミング言語を選択するコマンドが用意されていたのでそれを使って使用言語の選択をしました。
選べる言語はGo, PHP, Node.js, Javaで僕は普段から使い慣れてるGo言語を選択しました。

この時点でベンチを回してスコアを計測したら750くらいでした。

プロファイリングの設定

DBやNginxのログ解析のための設定をしました。 以下のサイトを参考にツールなどを設定。

周りの人はpprofなどを使って華麗に解析してたみたいなのですが、僕は導入することができなくて諦めました。。。

gitの管理など

いじっていてコードが消えたら怖いのでレポジトリをgitで管理する設定をしました。
そこでローカルに落として作業するか迷ったんですが、結局VSCodeのRemote SSHを使ってコードの編集はしました。

N+1問題の解決

アプリケーションのコードを見てN+1問題が発生してそうなところの修正を行いました。 しかし修正をしたのですがスコアは全然変わりませんでした。

ここで集中が途切れたので「小説家になろう」で俺TUEEE系の小説を読んで精神統一をしました。

インデックスを貼る

N+1問題を解決しても速くならなかったので無心でインデックスを貼り続けました。スロークエリログやNginxのログを見てボトルネックになってそうなクエリにインデックスを無限に貼り続けました。

この作業をすることでスコアが1500くらいになった気がします。ずっとスコアが変わっていなかったのでかなり安心しました。

強敵の出現

全てのクエリにインデックスを貼ったのですが、一つだけインデックスなどを貼っても一生速くならないクエリがありました。

SELECT 
  article_id, 
  count(user_id) as iineCnt
FROM 
  iines 
WHERE 
  updated_at >= DATE_ADD(NOW(), INTERVAL -1 MONTH) 
GROUP BY 
  article_id 
ORDER BY 
  iineCnt DESC,
  article_id DESC 
LIMIT 5

これの解決方法を2時間くらい悩んだのですが全然解決できません。
そこで息抜きにISUCONの解説記事などを読んでいました。するとキャッシュに関する記事が大量にあったのでこいつもキャッシュで解決できるのではないかと思いやってみることにしました。

結果、めちゃくちゃスコアが上がりました。確か2000を超えた気がします。1位だったので調子に乗ってすぐにツイートもしてました(間違えてこのツイート消してしまった。。。)

しかし1時間後に全体順位を見たらhppさんに抜かされていたので諦めて寝ました。

2日目

おはようございます

朝起きてすぐに全体順位を確認したらhppさんのスコアが3200くらいになってました。神すぎます。
追いつけるビジョンが全く見えなかったので今日はゆっくり自分のペースでチューニングをすることにしました。

トップページが遅すぎる

最初にログなどを解析しているとトップページが一番アクセスされる上に合計の実行時間が長いので、ここの改善をしようという方針を立てました。
しかし実行時間の遅いクエリなどは見当たらず何をすればいいか分からないで時間が過ぎました。

全部キャッシュ作戦

スロークエリログをよくよく見るとトップページのレンダリング時に呼び出されるクエリが異常に発行されていました。
そこで昨日のスコアを伸ばす要因となったキャッシュを用いてみることにしました。

するとなんということでしょう!
大量に呼び出されてるクエリの一つをキャッシュに乗せてみたらスコアが300も上がりました!!

これはもう全てキャッシュに乗せるしかない。
時間の許す限り全てのクエリをキャッシュに乗せ続けました。
スコアが絶対に上がると理解した上で書くコードは最高でしたね。

結果

最終的な結果はスコアが3173で全体順位は2位でした。
1位のhppさんとはかなりスコアが離れていましたが、なんとか2位になれてめちゃくちゃ嬉しかったです。

最後に

今回は初めてのパフォーマンスチューニングだったので、速度の改善方法などを調べながら手探りでしたがなんとかパフォーマンスをある程度改善することができました。今回でパフォーマンスチューニングの全体像のようなものを掴めたので機会があったらISUCONに出場したり、日々の開発に役立てていきたいと思います。終わってから振り返ってもとても有意義なインターンだったなと思います。

参加した皆さん本当にお疲れ様でした! また、主宰していただいたサイバーエージェントさんもありがとうございました!!