2016-09-19

[isucon] ISUCON6 予選通過しました

今回はついに予選通過しました。チーム名は円山町です。17日土曜日の予選当日にやったことをメモしておきます。

予選当日のタイムライン
10時
出社 (会社のオフィスから参加させてもらいました。大変感謝)
前の日の晩に作った無料試用アカウントでデプロイ
Go 実装に変更、動作確認
記事を削除したら /initialize しても復活しなくて、初期データを壊してしまったので復旧方法を調査
/var/log/cloud-init-output.log を見て展開イメージの tar.gz を発見したので、中に入っている SQL ダンプでデータを復元

11時
Go 実装に切り替えたところ、スターが付かない不具合があったので、コードを検査、ngrep で調査して原因を特定
ローカルでコードいじるためにホームディレクトリで git init、必要そうなものを add/commit して push
ローカルの MySQL にデータを入れて似たような環境を構築、バグ修正、動作確認
正常に動作するが、キーワードの置換処理があるページが遅くてベンチどころじゃないので、アプリに net/http/pprof を仕込んで、キーワード個別ページを叩いた時の CPU プロファイルを取得
htmlify の正規表現コンパイルと正規表現マッチングが遅いことが分かったので、何とかする方法を検討

12時
昼食、修正方針の検討

13時
htmlify で行っているキーワードの発見部分は、元上司の okzk さんが活用しているのを見たり、他プロジェクトのコードで見たことがあったトライ木で何とかするのが良さそうと判断、触ったことのあった github.com/armon/go-radix を使わせていただいて試作してみたところ、特に問題なく動き、動作はだいぶ速くなった。
ベンチを流しながらプロファイルを取ったところ、トライ木の構築に時間がかかっていたので構築済みのトライ木をキャッシュする (キーワードリストが変わったら破棄) ように修正

14時
isutar のスター追加処理でキーワードの存在チェックにキーワード個別ページを叩いていて迷惑なので MySQL から存在情報を取るように修正
isuda のスター取得部分で HTTP API を使う必要はないと思ったので直接 MySQL を参照して取るように修正

15時
SPAM フィルタの部分が明らかに何か怪しいので、isupam を10個に増やして nginx の upstream に入れてもらったりしてテスト
とくに改善しないので全て元に戻す
キーワードと内容をくっつけて isupam に投げても問題なかったので、これでリクエストは減らせたので良しとする

16時
キーワード本文のキャッシュを追加 (htmlify の先頭で同じ内容のリンク済み内容が分かってればそれを返す、キーワードリストの変更があったら破棄する)
トライ木の Insert, Delete で差分更新を行えば、完全な再構築を回避できることが分かったので修正、これで画期的にスコアが上がる
再起動テストを実施、起動直後の初期化で MySQL につながっていなくてアプリがクラッシュする問題を発見したので修正

17時
ユーザー名をキャッシュするように修正
記事全件数をキャッシュするように修正

終わってから気づいた点
/ のスター取得部分のスター取得クエリが記事の件数と同じ回数流れちゃってるのは良くない
htmlify で []string 作って Join したが十分な長さの ByteBuffer でやった方が良かったのでは
isutar を廃止して、スターをオンメモリ化できたのでは

参加された方のレポート見て出来ていなかった点
キーワード本文キャッシュ破棄を全破棄ではなく上手くやる方法


関連リンク
[isucon] ISUCON5 予選敗退しました
ISUCON4 に挑戦して予選敗退しました