BLOG::はるかさん

はるかさん のブログです。近況情報や技術的な話題など。

チーム「椅子子」でISUCON4予選で2日目5位でした

先週末、9月27日(土)、28日(日)の2日間行われたISUCON4の予選に参加しました。参加したのは2日目で、チーム椅子子は今のところ5位となっております(審査待ち)。無事に審査通過しましたら本選出場可能になる予定です。

主催のLINEさん、問題提供者のCookpadさん、そして出場者の皆さん本当にお疲れ様でした。去年ブログを書き忘れたので今年はがんばって書いております。

椅子子

去年に引き続き12年新卒同期エンジニアチームで参加しました。 チーム名に特に意味はありません。 去年isuconから適当にnをとって"isuco"というチームで出たんですが、今年は漢字にして椅子子にしました。 発音は定義されていませんが、"いすこ"または"いすす"と発音します。 椅子子ちゃん的なキャラクターが居ると良いと思います。

やったこと

スコアが伸びた要因はこんな感じ。

  • MySQLの設定とインデックス構築
  • ERBをやめる
  • GET /を静的ページにする

インデックスをはったらDBの負荷がなくなってしまったので、 あとは変更容易性を落としていくだけのチューニングになってしまったのが心残り。

自分がやったこととしてはこんな感じ。

  • 開発環境構築をAnsibleで自動化した
  • 中途半端にRedisに置き換えた
  • ブランチをマージしてはバグを修正した
  • 本番環境で定期的にベンチマークを動かした

2回大きなブレイクスルーがあったんだけど、どちらも他の2人におまかせしていてそんなに大きな変更はしていない。 その分本番環境でベンチマークとったり、マージしてバグ治したりすることに集中できたので役割分担的には良かったと思う。

コミットログから起こした記録

ベンチマークのグラフはこんなかんじ。

細かい設定は置いておいておおまかな流れだけ書く。 リポジトリを公開しておくので細かい変更が見たかったら参照すると良いかも。結構ひどいコードが見られる。

以下詳しく書いているので興味あったら読むと良いと思う。

10:00-12:00

とりあえずインスタンスを4台起動。 去年の問題をやったとき1人1つずつ本番と同じ環境の開発環境があった方が便利だったので最初から4台起動することにした。 すべてのインスタンスにAnsibleで全員のアカウントと基本的なツールをセットアップした。

去年はシェルスクリプトを実行してユーザの公開鍵を配置したりしたんだけど、Ansibleのplaybookにしたおかげでリモートから4台一気にセットアップできてとても便利だった。 今回使用したplaybookは以下のリポジトリにある。チーム伝統の最新のVimビルドも自動化されている。

ISUCON3の予選問題を練習していた時の設定をベースにしているので、環境構築に時間かかったりせずにすんなり作業に入れた。 この間他の2人にはアプリケーションの動作を確認してもらったり、リポジトリをつくったり、my.cnfの設定をしてもらったりしていた。 そんなことしてたら12:00位に。

12:00-14:00

このあたりは昼ご飯をなんにするか考えながらそれぞれコーディングしていた。 my.cnfがほぼ空っぽなのに気がついたので、redcap97にお任せして適当に設定したりインデックス張ったりしてもらってた。 redis化やってたけどインデックスだけで十分速かったのでリバートして最終ログインだけredisを使うようにしてマージした。 あとポートが枯渇してsysctl.confの設定を入れてもらった。

この時点でボトルネックがDBからアプリケーションに移っていてCPUを使っているのはunicornになった。 あんまりどうするか思いつかなかったので、rack-lineprofを眺めながらERBをやめてみたりしていたら10,000くらいは上がった。 最終ログイン日時が使われてないことに気づいて消されてたけど、 良心の呵責を感じて(ルール上は見た目を変更しちゃだめなので)他のメンバーの変更を修正して戻したりした。

14:00-16:00

お昼を食べてからベンチマーククライアントのリクエストの検証をはじめた。 他のメンバーがクライアントがリダイレクト先をちゃんと解釈していることに気づいた。

これを利用してリダイレクト時にクエリストリングを付けて、 クエリストリングみてレスポンスを出し分けることで/を静的に返すようになったのがブレイクスルーになった。 この時点でスコアが45,000くらいで2位になってた。

16:00-17:00

いよいよやることがなくなってきたのでいままでやったことを見直していた。 ここでcookie sessionを完全にやめたり、複合インデックスに張り替えたりしている。

遅いページは/loginだけになっていたけど、ここに手を付けると/reportも変えないといけなくて時間的に踏ん切りが付かなかった。この時点でこれ以上スコア伸びないのが決まったと思う。

topでみているとunicornよりbechmarkerの方がCPUを消費していた。 どうにかbenchmarkerのCPU使用率を下げようと思ってHTMLの容量を減らしたりしてみるけどあんまり効果なし。 「とりあえずGCをとめてみる」とか言ってて行き詰まってる感じがすごい。

17:00-18:00

見た目が保たれればOKというルールを思い出したので、DOMを変更せずにすべてJSでDOMを構築することを考え始める(JSでDOM構築されるからHTMLコードは変わっててもDOM構造は変化してないよね?)。/mypageをJSで処理するようにしたところで17:55位で、実装終わってなかったけどとりあえずベンチを実行したらスコアが500位下がったところで時間切れ。最終スコアは46,875。最大スコアは47,874だった。

あとで id:sfujiwara さんの記事みてわかったけど、linkタグをJSで書き出すようにすればそのリクエスト減るってとこまで頭が回ってなかった。

感想

ひとまず5位になれたのでよかったけど、もう1つ大きなブレイクスルーがないとこれ以上順位をあげるのは難しかった。/reportに手を付けるのが面倒で放置してた分が大きかったので、ここに手を付けてたら最後の2時間は有意義だったんじゃないかな。

ひとまず本選には(問題なければ)出られそうなので、11月8日(土)スケジュールをあけておこうと思います。 それまでに本番へのデプロイも簡単に自動化できるようにしておきたい。