ISUCON6で予選敗退してきた

今年も毎年恒例となっている同期チームで参加した。

素振り

素振りとしてPixivの社内ISUCONの問題をやった(某コミュニティでやった)。
素振り時に良かった点はこんなところだった。

  • 個々人の作業環境と本番環境を分ける
  • git管理して、本番への反映は本番でpullする感じ
  • アクセスログ、スロークエリの解析を行い、きちんとボトルネックを把握する
  • ログをリポジトリにぶち込んで見やすくする

事前準備

会社の会議室を広々と専有し、スクリーンに常にカンバンを表示したり、さっとホワイトボードが使えたり、ブラインドを開けて景色を良くしたり、とにかく作業しやすい空間を作った。
良い広さで、普段の業務もあんな感じの広々空間でできたら幸せだろうなとか思った。

当日のタイムスケジュールを大雑把に作った。
本当に大雑把で、これくらいしかなかった。

  • ○時までにしっかり作業を開始できる準備を完了させる
  • ○時になったらいったん手を止めて現状確認会をする x 2
  • 17時半になったら最終スコアを出す準備をする

Azureに慣れるため、チームメンバー全員でAzureのテンプレートから各自の環境を作る素振りをした。
最初はAzureの仕組みがよくわかっておらず、1つのリソースグループに同じテンプレートから複数個のインスタンスとかを立ち上げようとしていたができなかった。
そこで、人数分のリソースグループを作り、そこにテンプレートから作成する方法を試した。
このやり方で良かったらしく、無事、人数分の環境を作る方法を理解できた。

あとは、時間までGitHubのカンバンに必要タスクを追加していった。
その際、脳みそを空にして取り組めるような内容のものには、脳みそを空にして実行できる手順を書くようにした。

本番

自分がやったこと+感想

  • アプリをgitに載せて個々の環境でも動作を再現できるようにする
    • perlディレクトリ内に.gitignoreがあり、localディレクトリがignoreされていることに1時間くらい気づかず時間を無駄にしてしまった
  • Slow Queryをpt-query-digestで解析してボトルネックを探す
  • entry検索のボトルネッククエリを改善しようと、keywordの長さをカラムに持たせつつindexを貼った
    • 要件的に全件必要で、どうせフルテーブルスキャンになるから完全に無駄だった(というか複雑性が増しただけだった)
    • アプリを読めば、フルテーブルスキャンにならざるをえないことがわかったはずで、すぐにキャッシュの実装に入るべきだった
  • MySQLの設定をチューニング
    • たいした数ではないinsertがボトルネックになっていたので、パラメータをまともな感じにした
    • 結局insert自体は早くならなくて完全に無駄だった
  • keywordsをRedisにキャッシュする
    • 実装でハマってしまい3時間ほど無駄にしてしまい、これをやっているうちに競技時間が終わってしまった
    • なぜか更新タイミングの問題だと思い込み、更新をロックするように実装したが、もちろん意味がなかった
    • Perlが外部と文字列をやり取りする場合に文字列をEncodeする必要があることを完全に忘れていたのが問題だった

チームメンバーがやったこと

  • テーブル情報を抜き出す
  • アクセスログの解析
    • nginxが解析に必要なログを吐き出す設定
    • alpを使って解析
  • Perlの鯖をStarletからGazelleに変更
  • 定番のnginxの設定をぶち込む
  • PerlのWorkerを増やす
    • 2コアしかないマシンなのにWorkerを20にしたら地味に大きくスコアが上がって草生えた
  • keywordsのselectをhtmlfyを呼び出しているループの外へ移動
    • これでスコア上がった
  • isutarを破壊してisudaに統合
    • web部分だけ統合
    • 時間無くてDBは統合できなかった
  • isupamへのリクエストをkeyword/descriptionを結合した文字列にしてまとめた
  • BIGINTだったカラムを全てINTに変更

良かったこと+感想

  • GitHubのProjectを使い、やれること、誰が何をしているかを把握できるようにする
  • 会議室を広々と使い、話す時にさっとホワイトボードが使える状態
  • 効果がなかったが経験としてよかったのは、テーブルの構造を変えたこと
    • 過去2回のISUCONでは、怖くてテーブルの構造を変えることができなかったが、一歩踏み出すことができたのは大きい
  • 2年前からの1段階目の目標として「スコア1万を超える」というのがあり、目標を超えられた
    • 今回は22,220だった
  • 過去よりもいろいろなことにスムーズに取り組めるようになっていた

今回は、アプリのコードを読んでいじる部分の重要性が高かったように感じた。
MySQLだけ見たりnginxだけ見てもほとんど意味なかった。
総合的に判断する必要があるなーという学びを得た。

次回あればやりたいこと

細かいこと大きいこと含め、備忘録として次回やりたいことをざっと書いておく。

  • 素振りは複数回実行する
  • みんなでサービスを触りつつコードの理解に時間をかける
  • DB起動時にBuffer Poolにデータを載せる
  • 正規表現があったら事前コンパイルしておく
  • 自分の作業環境を使いやすく整える
  • nginxでgzip圧縮
  • チームメンバー的に読みにくいコードを、さっと読みやすい形式にスタイルだけリファクタリング
  • 過去問に対する他チームのアプローチを勉強する
  • Redis/Memcachedを事前にちゃんと使う

終わりに

多大なる時間と労力をかけて準備してくださった運営の方々、ありがとうございました!
今回も楽しく勉強になりました。