ISUCON5 の予選2日目にチーム「chatzmers」として参加し、予選2日目2位・総合4位通過 という結果を残すことができました。

まず、チームメイトであり 弊社 の 2013 新卒で同期でもある @Maco_Tasu@rg_gs に感謝。そして、運営チームの皆様にも感謝。ボリューム感とやりがいのある問題で、最後まで ISUCON を楽しむことができました。

ということで、せっかくなので予選当日までの期間も含めてどう ISUCON5 に立ち向かったのかを自分視点で書こうと思います。不足している点についてはチームメイトのエントリをご参照いただければと思います。


当日までにやったこと

まず、予選当日の1ヶ月くらい前に決起会を行い、チーム名(最後に詳しく書きました)と予選当日までどういうスケジュールで動くかを決めました。あとは、Slack の team や GitHub の private repo なども準備しました。

一般的にシルバーウィークと呼ばれていた期間は浮世の輪廻から解脱して ISUCON4 の復習と準備に捧げました。やったことをざっくり並べると以下のような感じです。

  • ISUCON の勝ち方 を何回か見て頭に入れる
  • kataribe や pt-query-digest などの解析系ツールの基本的な扱い方を把握して、実際に手を動かして使ってみる
  • 実際に ISUCON4 の予選問題を GCP に立てて、50,000 くらいのスコアを出せるまで地道にチューニング
  • 予選前日に公開された tkuchiki さんの alp も基本的な扱い方を把握して、実際に手を動かして使ってみる(本当にお世話になりました)
  • 上記のやったことを予選当日にロスタイムなく再現できるようにドキュメント化

振り返ってみると、予選当日に練習でチューニングしきったインスタンスの中身やまとめたドキュメントを参照する機会が多々あったので、そういったものをシュッと参照できるような環境を事前に用意できていたのはよかったなあと思います。


当日やったこと

正直、自分が予選当日にやったことは全部 ISUCON4 の予選問題の復習でやったことといっても過言ではないので、あまり面白くはないと思います。

基本的には、ミスなく素早く自分にできることだけやるぞ!!!という方針でした。普段からその偉大さを目の当たりにしている大先輩方に、経験値も技術力も劣っている自分が噛みついていくにあたって、無駄にできる時間は欠片もなしです。

早朝

ただひたすらに精神統一。事情があってオフィスに宿泊していたので、6時起きしてサウナに行って帰ってきてトイレの個室で事変の 能動的三分間 をただひたすらリピート。

午前

開始前に決めていた役割分担に基づいて作業開始。

  • @Maco_Tasu:コードを読んでアプリケーションを把握する
  • @rg_gs:事前に準備してくれていた GitHub への push にフックして自動 deploy するくんを動かす
  • @m0t0k1ch1:Perl の初期実装でベンチマークを回してアクセスログとクエリログを解析する

ただ、全員 systemd 初体験だったので、、@rg_gs に使い方を調べてもらうことに。ここで Slack に #systemd チャンネルが生まれ、よく使うコマンドをメモる用に使ったりしました。

アクセスログとクエリログを解析して、コードを読んでいた @Maco_Tasu の見解と照らし合わせた結果、ボトルネックになっているエンドポイントとつらいクエリがざっくりと把握できたので、

  • @Maco_Tasu:/ を地道になんとかする担当
  • @rg_gs:/footprints の group by をなんとかする担当
  • @m0t0k1ch1:/friends の or をなんとかする担当

という感じで担当を決めました。確か、もうこれでお昼くらい。。

ここで結構大事だったのが、以下のような branch の運用ルールも決めてしまったことかなと思います。

  • 担当箇所ごとに作業 branch を切る
  • 作業 branch には必ずベンチをかけてスコアが上がることを確認してから master に merge する(master の品質を保証し続ける)
  • 上記の merge はできるだけ細かい単位で行う
  • スコアが伸びなかった作業 branch は master には merge せずに待機させておく

これは結構うまく回った感じがします。

あと、午前中に自分が他にやれたことは以下くらいでした。

  • Starman を Gazelle(unix domain socket)に変更
  • nginx.conf を最低限調整
  • 静的ファイルは nginx で捌くようにする

ボトルネックへの直接的なアプローチではないですが、やっておいて損はない類のことだろうと思ってシュッとやりました。スコアも地味に伸びてくれていたと思います。

昼下がり

自分は /friends をなんとかする担当だったので、とりあえず関連するコードを読むところからスタート。比較的早い段階で oneanother の双方に対する条件を where 句に含める必要がないことに気づけたので、

  • one だけに対して条件を指定するように修正して、インデックスが効くことを確認
  • ループクエリを join に修正

しました。

修正後のアクセスログを alp で解析したところ、レスポンスタイムはだいぶ下がっていたので、一旦 /friends の修正はここまでにして、

  • users をアプリケーション起動時にプロセスメモリにのせる
  • @rg_gs と一緒に /footprints を修正(user_id で group by する必要はないのでしないようにする + user_id にインデックスを貼る)

という感じで手を動かしながら、「細かく修正を入れる、ベンチをかける、アクセスログを alp で解析」というルーチンを繰り返していました。

このあたり、スコアはちょいちょい上がるものの爆上がりはしない低迷期だったのですが、@Maco_Tasu の「神対応」というコミットメッセージつきの修正でスコアが一気に 16,927 まで伸びて暫定トップに。さすがに叫びました。

ここで @Maco_Tasu がやっていたことは 彼のエントリ をご参照ください。

夕方

alp の解析結果を見る限り、明らかなボトルネックは潰せてきていたので、

  • @Maco_Tasu:プロセスメモリにのせてある users を活用できるところは活用する
  • @rg_gs:comments の count を Redis で管理する(これは結局 /initialize がうまく回り切らず断念。。。無念)

といった修正を入れてもらいながら、自分は ISUCON4 の復習でやったけれどまだ今日やれていないことを順番に潰していくことに。具体的には、

  • 思い切って試しに MyISAM にしてみる(なんとスコアが 2,000 〜 3,000 上がって、このあたりで 20,000 を超えました。。本戦までに要検証)
  • base.tx を使わない(スコア微増)
  • /login は GET のときだけ nginx で捌く(ほぼスコア変わらず)
  • ログイン判定もプロセスメモリ上だけで完結させる(これは正直スコア上がるやろ!!!と思っていましたが変わらず。。。)

など。とにかく「まだできることはあるのに手は止めまい」という想いでした。

残り時間が30分を切ったあたりで、例の「タマキ」に二度遭遇して相当焦って直近のコミットを revert したりしたものの、スコアは 20,000 を超えたあたりでだいぶ安定していたので、ベンチを何度もかけてスコアの再現性と諸々不備がないことを確認して、追い込みで飛び越されないように祈りを捧げながら、終了。

結果、最終スコア 21,242 を記録し、予選2日目2位・総合4位。無事、本戦に出場できることになりました。正直ここまでいけるとは思っていなかったので、結果が確定したときは相当量の喜びを噛みしめました。


最後に

チーム名「chatzmers」の由来

正直、個人的にはチーム名に全ての指針を宿したので、ここから勝負は始まっていたと思っています。まるで茶葉を摘むが如く着実に1つ1つボトルネックを摘んでいきたい、そんな想いが込もっています。実際の闘い方もそんな感じでした。

あとは一発屋っぽい名前にしたくなかったこと。「茶柱 in the house」というチーム名が先に候補として挙がっていたのですが、「予選敗退してそう」ということでボツにしました。

チームメイトについて

@Maco_Tasu とは普段から同じプロジェクトで動いているので、基本的に believe していたのみでした。結果、最高のスコアアップで最高の体験をさせてもらえたので、本戦も基本的に believe していこうと思います。

@rg_gs は予選当日までの期間も含めて足回りを固めてくれた印象。茶摘み自体を円滑化していくその姿勢と渋さは流石。将来は茶摘鋏職人か。本戦では謎のよもぎ餅発言を超える発言が期待されます。

2人とも、ありがとう。本戦はさらに進化して臨もう。引き続きよろしくお願いします。

本戦に向けて

一昨年に運営のお手伝いとして参加しただけでも興奮した本戦にプレイヤーとして出場できるのは感慨深いです。予選の反省点をしっかり整理したうえで、本戦までに摘める茶葉はきっちり摘みきりたいと思います。合掌。