運が良かったのでISUCON8で優勝しました

Webサービスのチューニングを競い合うコンテストであるISUCONの第8回本戦に出場してきました。
実際に何をやったのか、詳しい内容はwhywaitaが書いてくれているのでこちらでは補足情報などを書きます。

blog.whywrite.it

チームについて

実はISUCON自体に参加するのは今回が初めてではありません。 このチームは2年前に結成してISUCON6から参加していたのですが、ずっと予選落ちで本戦には一度も出場したことがありませんでした。 メンバーはwhywaita, nomeaning, icchyの3人で、TokyoWesternsというCTFチームの中でもインフラ系に明るいメンバーで構成されています。 ISUCONの存在自体は以前から知っており、出てみたいという3人でチームを組むことになりました。

ISUCON6

最初にこのチームで出たときは「院試 in 死」というチームでした。名前の通り院試に苦しんでいた学部4年生の時のチームです。 言語は特に決まっていなくて、得意な言語はnomeaning→Ruby、icchy→Pythonという感じだったので、両方試してみて良い感じの方を使っていました。
結果はほとんど覚えていませんが、学生枠での予選突破すら難しいレベルだったと思います。 予選直後にGo言語がめっちゃ強いという話を聞いて、次からGoにするかみたいな話を冗談半分でしたのを覚えています。

ISUCON7

詳しい経緯は覚えてないのですが、覆面チーム(普段使っている名前を隠したチーム)にするかという動きになり、latin_cross 入院中 latin_cross (fried_chicken,backslash,6sec_dec)というチームで出ました。誰が誰なのかわかりませんね。
この時はGo言語で実装をしていましたが、Cache-Control: publicに気づかなかったのであまり得点が上がらず予選敗退となりました。

f:id:icchyr:20181023115835p:plain

実を言うと偶然40000点くらい出た時があって、そこで止めていれば学生枠で予選突破だったかもしれません。(画像にあるtmpというチームが学生枠最後のチームです) ベンチマーカーガチャの攻略が必要だということを学びました。

ISUCON8

今回のISUCONも覆面チームで出る流れになったのですが、全然案が出なかったところリーダーであるwhywaitaのアイデアで決まりました。

f:id:icchyr:20181023120925p:plain

なぜタイムゾーン云々の話をしているかというと、僕が4月から半年間アメリカに行っていて、予選の時はUTC-7から参加していたためです。 他の二人は日本にいましたが、つじつまを合わせるためにどっちか片方がサマータイムってことにすればええやろってことで、社会人に比べても朝早くから出勤しているnomeaningはJDTになりました。
ちなみにアメリカは18:00~2:00で、研究室から参加していたのですが、終わった後discordやtwitterやSlackに張り付いていたので朝方帰宅しました。 競技時間中はSlackでボイスチャットを繋いでコミュニケーションを取っていたのでリモートワークみたいな感じでサクサク作業できましたが、手書きで情報を共有する手段がなくて、やはり集まるのは大事ですね。

学部4年から3回目ということは全員修士2年で、少なくともwhywaitaは来年就職するため今回が学生チームとして出られる最後のISUCONだったので、今回こそは絶対に本戦行くぞと意気込んでいました。
学生枠で通れたら良いなくらいにしか思っていなかったですが、幸運にも一般枠で通過することができて結構盛り上がってました。

ISUCON本戦

初めての本戦なので結構緊張していました。 事前のマニュアルをほとんど読んでなくて、会場に入ったらまず席を確保しないといけないことを知りませんでした。 我々が到着したのは9:30くらいだったのですがほとんどの机は埋まっていて、円卓はちょっと狭かったので最終的に自販機の前のカウンターテーブルのような場所に座りました。 机が高いので椅子も高く硬く、長いこと座っているとお尻が痛くなるので結構立ったまま作業していたのですが、スタンディングデスク割といいですね。 ISUCONなのに椅子に座らないとはこれいかになんてくだらないことを考えていましたが、意外と作業しやすかったです。

競技の方ですが、whywaitaのタイムラインにもある通り最初1時間くらいはほとんど何もしていませんでした。docker-composeは手元の環境構築を楽にするための優しさなのかなと思いましたが、restartするたびにdocker-compose buildが走って厄介なので何も考えずにnginxとappを剥がしました。 MySQLはバージョンが8だったのでCentOSの上で動かすのがだるいなと思いましたが、そこはwhywaitaがやってくれたので助かりました。

あとは概ね例のタイムライン通りで、僕はコードをあまり書かずにひたすら眺めて、怪しそうだなーと思うポイントを適当に共有していたらいつのまにか高速化されていました。特に何もしてないですね。

今回優勝できたのは本当に運が良かったと思っていて、得点の減点ルールが割合によるものだったことが非常に大きいと思います。 実際takedashiはもっと多くの要素に気づいて高速化をしており、終わった直後に交わした会話からしてもこれは5万点いってるし負けたかな、という印象を受けたのですが、実際には減点で6割くらいまで得点が落ちていました。 今回のアプリケーションは決済系なので、リクエストを落としたら大きな減点に繋がるのはまあ確かに、と思いました。 顧客が増えれば増えるほどわずかなミスが命取りになるわけで、点数をあげればあげるほどエラーに注意しないといけないということですね。
競技終了1時間前に謎のfailが多発していたので安定化を真っ先にやるべきだったのですが、僕はしばらく別の高速化に取り組んでいました。 戦略としては4, 5万点を狙うよりも0にしない方を取るべきなのは当たり前で、ここは反省点です。 特にISUCON8は予選の段階でリクエストが増えてくると死ぬパターンがあったので、安定させて減点を減らすことに注力するのが最善だったのかもしれません。( enable_share を見つけたときにこうなるだろうという予感はしていました)

他の参加者と話して一番なるほどとなったポイントはやはり enable_share のABテストで、確率で返すという発想が全く思いつきませんでした。 確率でボタンが消えるなんて実際の利用者は困惑すると思いますが、サービス全体の体験が悪くなるよりかは確かにマシだと思います。 とはいえ enable_share をtrueにした状態でベンチを通過するのは必要だろうと思っていたので、結果的には良かったです。


繰り返し書きますが今回は本当に運が良かったと思います。 煽りのつもりは一切ないことを事前に断っておきますが、社会人でもあまり調子が出ない問題セットはあるということと、学生でもかなり腕の立つ人がいるということに驚きました。今回特別賞 (もっとも早く15000点を突破したチーム) はNaruseJunでしたし、予選では学生かつ一人チームであるtaildさんは全体4位でした。 懇親会で小耳に挟んだ「社会人はもうダメでこれからは学生だ」というフレーズがあって、僕は学生が社会人に安定して勝つのはまだまだ無理だと思っていますが、特定の分野なら勝てる!というケースはなくはないのかな、と思います。ただ今回は本当に運が良かったです。

本戦で学生が優勝するのは初らしく、優勝賞金100万に加えて学生優勝30万も頂いてしまいました。LINEさんありがとうございます。 パーっと使う気はないですが、アイコンにもある通りトンカツが好きなので美味しいお店を教えてもらえると喜びます。お待ちしております。

最後に、運営のみなさま本当にありがとうございました。(ガチャはありましたが)ベンチマークはサクサクで、開始時間が延期することもなく、問題も予選・本戦ともによく練られた良問でした。 次回も是非参加したいと思います。