Write and Run

it's a simple way, but the only way.

ISUCON12予選にRubyで出場して8位で予選通過した(ソレイユ)

霧矢あおい(KOBA789)です。

タイトルのとおり、ISUCON12予選に Ruby で出場して8位で予選通過しました。最終スコアは34635(ベストと等しい)です。

本戦出場は ISUCON9 ぶり2回目です。

チーム「ソレイユ」

今年は私の多忙もあってチーム解散の危機だったんですが(チームメイトにはご迷惑をおかけしました)、無事いつものチームで出場することができました。

霧矢あおい「無事、チーム『 ソレイユ』の一員になれました。ありがとうございました!」
ひとりチームからソレイユへの移籍に際して運営さんにお手伝いいただき、無事移籍を成功させたときの様子。

というわけでメンバーは以下:

アイカツ劇場版公開おめでとうございます。忙しくてまだ観られていません。

たたかいのきろく

うちのチームは例によって Git をほぼ使っていないので正確な記録はないのですが、今回は私が ToDo リストを書きながらマネージャーっぽいことをしていたのでそれをベースに書きます。

  • 10:00 競技開始
    • KOBA789 & s4ichi: レギュレーション読み合わせ開始
    • osyoyu: 競技用サーバーに入って開発環境構築開始
  • 10:20 頃
    • KOBA789 & s4ichi: とりあえずブラウザでアプリケーションを触ってメンタルモデルを構築
  • 10:30 頃
    • KOBA789 & s4ichi: とりあえずコードを上から下まで流し読み。雰囲気を掴む
    • KOBA789: 「SQLite3 がいつもの戦い方を阻害するので MySQL への移行を視野に入れた方がいい」
  • 10:50
    • osyoyu: 開発環境構築完了
    • all: KOBA789 から osyoyu へ、課題のアプリケーションのメンタルモデルを共有
    • osyoyu: 「いつものツール使うのに Docker 邪魔なので降ろした方がいい」
    • osyoyu & s4ichi: Docker 降ろし開始
    • KOBA789: DB へのアクセスパターンの洗い出しを開始
  • 12:00
    • KOBA789: DB へのアクセスパターンの洗い出しを完了。MySQL への移行が現実的な規模であることを確信
    • osyoyu & s4ichi: Docker 降ろし完了。いつものツールで開発・分析が可能に
    • KOBA789: 「移行を見据え、すべての SQL に名前をつけてメソッドに切り出したい。移行しなくても書き換えに役立つ」
    • all: 手分けして SQL 呼び出しのメソッド切り出しを開始
  • 12:30
    • all: メソッド切り出しが完了
    • s4ichi: 切り出したメソッドを使うように変更を開始
    • KOBA789: ranking のアルゴリズムの読解を開始(味集中カウンターへ)
    • osyoyu: visit_history の Redis 化を開始
  • 12:45
    • KOBA789: ranking アルゴリズムの読解が完了。player_score はプレイヤーひとりあたり最新の1行だけを保持すればいいことに気づく
    • KOBA789: player_score のデータ構造の最適化と MySQL への移行を同時に開始(player_last_score テーブルを MySQL に作る)
  • 13:19
    • KOBA789: player_last_score 対応のアプリのコード書き換えが完了
    • KOBA789: player_last_score の初期データ作成スクリプトの開発開始
  • 13:50
    • KOBA789: player_last_score の初期データが完成
    • osyoyu: visit_history の Redis 化がバグり散らしたので断念
    • osyoyu & s4ichi: player & competition の MySQL 移行を開始
    • KOBA789: MySQL 移行完了後の一手を考えるため、プロファイリングとタスク整理の旅に出る
    • なおこのへんまでスコア変化なし
  • 15:40
    • osyoyu & s4ichi: MySQL 移行完了
    • s4ichi: 移行完了を確かめるため、SQLite 周りのメソッドを noop に書き換え開始
    • osyoyu: いつもの分析ツールが使えるようになったため、MySQL にインデックスを貼ってスロークエリを潰し始める
    • KOBA789: player_score CSV の入稿で1件も保存されずに不整合でペナルティを食らう原因を調査開始
  • 16:18
    • KOBA789: ペナルティの原因は DELETE & INSERT によるデッドロックトランザクションが ROLLBACK してるからと判明。バルクインサートにして解決を試みる
    • s4ichi: 地道に N+1 を潰し始める
    • osyoyu: 完全に MySQL に移行できたため、満を持して複数台構成へ
    • このへんでスコアが一気に跳ねて25000くらいに
  • 17:00 頃
    • s4ichi: 「player の INSERT で dispense_id が遅い」
    • KOBA789: dispense_id を Redis INCR 化
    • osyoyu & KOBA789: visit_history の効率化に再挑戦開始
  • 17:40 頃
    • osyoyu & KOBA789: visit_history がまたもやバグり散らしたため断念
    • s4ichi: デバッグログを無効化
    • デバッグログ切っただけで1割くらいスコア伸びた
  • 17:50 頃
    • s4ichi: YJIT 有効化
    • YJIT は意味なかった(MySQL がパツパツで Ruby が遊んでいたため)
  • 18:00 競技終了
    • 17:00 から本質的な改善はなく、デバッグログを切ったことによるスコア向上だけでフィニッシュ

リモートソレイユと味集中カウンター

うちのチームはいつも1つの物理空間に3人で集まって戦うスタイルだったのですが、今年は初のリモートソレイユでした。

物理空間の大きな特徴として、ブロードキャストが容易であるという点があります。たとえば同じ空間にいる場合、その場で声を出せばなんの工夫がなくても他の2人に伝わるでしょう。

一方で、互いが遠隔地にいる状況ではそうではありません。音声はなんらかの通信手段を用いて意識的にブロードキャストしなければ伝わりません。これは物理空間と比較して(直感的には)不便な点です。

しかし私はこの特性を逆手に取り、従来あったコミュニケーションの課題を解決することにしました。

物理空間では「ブロードキャストが容易である」と述べましたが、裏を返すとそれは、受け取る情報のフィルタリングが難しいということでもあります。

私達のチームでは、しばしばペアプログラミングが発生します。難しい変更でバグが出たときなど、ひとりではパニックや視野狭窄に陥ってしまいがちなシチュエーションでは、ペアプログラミングはひとりよりも冷静に問題に対処できるため、2倍の人的リソースを投入してもなお結果として効率的なことがあるためです。

ペアプログラミングをすると必然的に声によるコミュニケーションの量が増えます。そしてこの声は、物理空間では必ずブロードキャストになります。ペアでないもう一人にも声は到達します。他人が悩んでいる声というのはとても気になるものです。特に私は気になってしまうタイプです。

たいていは2人だけで解決できますし、たとえ3人の知恵を同時に投入した方が解決が多少早かったとしても、3倍の人的リソースを投入するのが合理的な課題というのはそう多くありません。多くの場合、ただの野次馬根性で首を突っ込み、貴重な時間を浪費するだけになります。それくらいなら、チームメイトを信頼して背中を任せ、もうひとりは別の問題の解決に向けて深い思考をすべきでしょう。

やや遠回りな説明になってしまいましたがまとめましょう。従来あったコミュニケーションの課題とは、物理空間ではどうしても声が気になってしまい(主に私)、ひとつの問題に余計に多くの人数で取り組むことになって効率が悪くなることがある、ということです。

今回、私達のチームではコミュニケーションツールとして Discord を選びました。そして、上述の問題を解決するため、ひとり専用のボイスチャンネル「味集中カウンター」を用意しました。

チームのDiscordサーバーには、ひとりしか入れないボイスチャンネル「味集中カウンター」がある

他のチャンネル名が意味不明なのは見なかったことにしてください。語ると長い経緯はありますが、深い意味はありません。

ひとりで集中したいとはいえ、すぐに声をかけられないのでは不便です。時間の限られた ISUCON という競技では、メンション送ったけど反応がないというようなことがあると貴重な時間を無駄にします。

さて、Discord には他のツールにない機能として、あるボイスチャンネルにいるユーザーを強制的に別のボイスチャンネルに移動させるという機能があります。味集中カウンターはこの機能を使ったアイデアです。

まず、集中したい人は味集中カウンターに入ります。そして黙々と作業をします。もし、他のメンバーが一蘭を食ってる人に用があるときは、先述のボイスチャンネル間の強制移動機能で「再起動試験(あっさり)」チャンネルに呼び戻します。するとすぐに声をかけて相談等ができます。相談が済めば、麺が伸びないうちにまたカウンターに戻ります。

こうして、「集中したいときは他人の声をシャットアウトできるが、用があるときはすぐに声をかけられる」という仕組みが完成しました。

本戦に向けて

まずは Ruby を本戦に連れて行けて嬉しいです。やはり本戦に出るからには目指すは優勝です。Ruby にもう一度てっぺんの景色を見せてあげられるまで諦められません。

おまけ

感想戦配信のアーカイブがあるのでよかったら観てってください。はじめて凸待ち配信をしたのですが、たくさんの方とお話しできて楽しかったです。

youtu.be