ISUCON7開催に寄せて。もしくはISUCON6予選問題作問奮闘記
ISUCON7開催決定 めでたいですね。開催されるかどうかハラハラしていたので、開催が決まって良かったです。
考えてみたら、昨年のISUCONに関して個人ブログの方に何も書いてなかったので書いてみます。書いたら「とにかく辛かった」みたいな話ばかり出てきそうなので、それが影響して今年の問題作成に名乗りを上げる人がいなかったら困るなと思って、書くのを躊躇していた部分もあります。
問題作成することになったきっかけ
2015年末当時の話になりますが、過去3回優勝させてもらっていたので、そろそろお鉢が回ってくるんじゃないかとは思っていました。過去のISUCON優勝者、もしくは上位入賞者を擁する企業の中で、はてなはまだ問題作成をしていなかったからです。
回ってきたら困るな、と思っていたのも事実です。過去の問題作成者に比べると、僕は明らかにエンジニアとしての実力が見劣りするからです。過去の優勝もチームメイトに恵まれていたからです。また、ISUCON3では僕はfujiwaraさんの下、問題作成チームにいたのですが(当時仕事がデスマっていたのでチームにいただけで結局特に作業はしなかった)、その内部事情を知っていて、問題作成がいかに大変かを身をもって知っていたと言うのもあります。
ただ、話をもらったら受けるしか無いだろうな、とも思っていました。
そんな折、忘れもしない2015/11/13(金)にmorisnite #3というISUCON5の打ち上げ的なイベントがあり、そこで案の定 941さんにISUCON6の問題作成の打診を受け、引き受けることにしました。引き受けた理由としては以下の様なものがありました。
- pixivさんとの共同作問という座組が良さそうだったこと
- 社内のチーフエンジニア陣が乗り気になってくれたこと
- ISUCONに恩返しをしたかったこと
その時点で、941さんはpixivさんとの共同作問という座組を考えており、pixivのedvakfさんも問題作成に意欲を示しており、心強く思えました。また、これはあとで決めたことですが、片方が予選、片方が本戦を作って相互にレビューする仕組みも、スケジュールを守れそうだな、と感じたのもあります。
社内で問題作成の協力をまず僕以外のチーフエンジニアに呼びかけたところ、motemenとwtatsuruが両者とも前向きで頼もしい反応を示してくれたのも大きかったです。
また、やはりISUCONに何か返したいという思いもありました。賞金もありますが、何よりISUCONのお陰で僕のことを知ってくれる人も増え、業界内で仕事がしやすくなった部分も少なからずあります。このあたりは、妻にも「ISUCONに色々なものをもらっているのだから返した方がいい」と言ってもらい、背中を押してもらいました。
そういう経緯でISUCON6の問題を作成することになったのです。
本戦と予選、どっちを担当するかは、pixivさんと話し合ったのですが、両者が予選を希望したので、じゃんけんの末はてなが予選を担当することになりました。最初は「7月くらいにはお互い問題を出し合おう」とか言っていた記憶があるのですが、結局お互いギリギリになりました。
作問にあたって
僕はISUCONが「インフラエンジニアのコンテスト」だと言われることに対しては違和感がありました。また、OSやミドルウェアのチューニングだけで勝てると思われてさえいることは明らかな誤解だな、と感じていました。
OSやミドルウェアを適切に素早くチューニングできる能力と、アプリケーションのコードを正確に書き換えられる手の速さが両立してこそISUCONに勝利できると思っていたからです。
僕は、Webアプリケーション開発の現場にいてスキルを磨いてきたので、アプリケーションエンジニアとしての挟持がありました。なので「アプリケーションエンジニアならでは」の問題を作りたいな、と考えていました。
それが結果として、競プロ勢に向いた問題になった部分があるのかもしれません。予想は全くしてませんでしたが。
コンセプト決め
本当は5月のGWくらいにはコンセプトを決めて手を動かし始めたかったんだけど「みんなのGo言語」の執筆もあり、結局スケジュールは後ろ倒し。
「無駄なマイクロサービス」というコンセプトは僕の中に当初からあったのだけど、それだけじゃ足りないな、と思っていたのだけど、7月頭にmotemenがキーワードリンクのコンセプト実装を作ってきて、これはイケそうだということで、それを盛り込むこととしたのです。
結果として以下のようなものをつくることにしました。
- はてな(キーワード|(匿名)?ダイアリー)を模したブログとWikiの中間の様なアプリケーション
- キーワード自動リンク機能あり
- はてなスターのようなお気に入りを付けられる機能もあり
- 記事投稿時にはスパムチェックがあり、一部の禁止ワードや、アダルトサイトへのリンクが含まれている場合には投稿できない(これは後から追加したアイデア)
- それぞれ無駄にマイクロサービス化されている
作問
当初は以下のような役割分担になっていました。
- 初期実装作成: motemen
- ベンチマーカー・競技用ポータル作成: Songmu
- インフラ全般: wtatsuru
- 多言語移植: それぞれでやりつつ社内で募る
しかし、7月に前CTOのstanakaの退職を知らされ、motemenがCTOになることが決まり色々それどころじゃなくなり、僕が初期実装も作成することになりました。
7/13(水)-7/15(金)に夏期休暇を取得したのだけど、そこは自腹で渋谷のアパホテルに自主的に缶詰になり、そこから週末にかけて問題を作りました。isupamという雑なスパムチェックマイクロサービスを盛り込むことにも成功し、結構この時点で手応えを感じ始めていました。
8/13(土)-8/15(月)にかけても夏期休暇を取得し、そこではベンチマーカーを作っていました。ベンチーマーカー作成にあたっては、tagomorisさんがISUCON5時に作成したJavaのベンチマーカーフレームワークや、pixivさんの社内ISUCONで使われたベンチマーカーがめちゃくちゃ参考になりました。特にPuerkitoBio/goquery は便利で、これが無かったら、ベンチマーカー作れてたかどうかあやしい。
その翌の8/16(火)が、MSさんに集ってpixivさんに参考実装を解いてもらうリハーサルの日だったのだけど、なんとか雑な準備が終わったのが、本当にその日の未明でした。それがこの日。
リハーサルでは「ちょっとボリューム少ないんじゃないか」という指摘も受け、ボリューム増やすかどうか迷ったんだけど、そのままで行くことにした。その時点ではPerlの参考実装しかなかったため、参考実装のコードを固めて、他の言語に早めに移植を開始したかったというのが一番の理由。最終的に、多言語実装との間での調整に苦しむことになるので、ここで色気を出さないでよかった。
他言語実装・インフラ準備・最終調整
8月末からの1ヶ月が最終調整期間。競技用ポータルサイトはmotemenが作ってくれて助かった。僕は、ベンチマーカーをスケールさせるためのワーカーシステムとそのポータルへの繋ぎこみをやっていた。この辺の仕組みは結構よくできたと思っていて、pixivさんも本番に流用してくれました。ワーカーシステムがなんとなくできたのが、9/4(日)くらい。
多言語移植は、pixivさんや社内のエンジニアがかなり協力してくれて助かりました。多言語実装、大変に思われるかもしれないし、実際大変なんだけど、複数人の僕じゃない人が移植することで、ベンチマーカーのバグに色々気づけたのは逆に良かったように感じています。具体的には想定していないレスポンスを受けるとベンチマーカーがクラッシュするといったケースを見つけられました。
最後の1週間は言語実装毎にあまりにも初期スコアがバラつくのに苦しみました。特に言語ごとに正規表現エンジンの性能に差があり、性能の悪い言語だと全然スコアが出ないという問題に苦しめられました。キーワードの初期データは、最初は20000ワードから調整段階で増やしていくことを想定していたのですが、結局7000ワードくらいまで減らすことになりました。
また、競技用データはWikipediaで公開されているデータをサンプリングして利用していたのですが、チェッカー側で誤判定する記号が含まれているワードを丁寧に除外したり、誤検知が起きそうなワードをこれも個別に除外したりと、データセットを作るのにもかなり時間をかけることになりました。抽出スクリプトや検査スクリプトを書きまくり、何度もデータの作り直しやサイズ削減をおこないました。「なんて問題を作ってしまったのだ」とこの時は自分自身を恨みました。
予選直前の9/14(水)-16(金)の期間は丁度京都出張が入っていたので、京都のメンバーと顔を突き合わせて業務時間後に作業ができて助かりました。つまり直前まで調整していた。
とは言え「ISUCON5のデスマよりまし」だと自分に言い聞かせて頑張っていました。最後の数日徹夜とかはありませんでした。もともとISUCON5の問題作成がいかに過酷だったかはkamipoさんから散々聞かされており、それもあって僕は恐怖におののいていたのです。
幸い、インフラ構築は、wtatsuruとy_uukiに任せることができたので助かりました。僕は予選で利用する運営側のサーバーにmackerel-agentを入れる設定を書いたくらい。
オンライン予選の運用
オンライン予選参加チームが317チームだと聞いた時は、覚悟はしていましたが、マジか…、とだいぶくるものがありました。初日と二日目それぞれ150チーム強ときれいに分かれていました。
過去のオンライン予選では、運営がリモートベンチマーカーシステムのスケールに少なからず苦労していたのが見受けられたので、そこの設計と運用、それに加えてそれらのモニタリングをちゃんとやらないといけないと考えていました。
ベンチマーカーノードは単純に
ベンチマーカーノードは1ノード1VM専有とし、起動したら勝手にベンチマーカー群にジョインするようにしました。これにより、Deploy to Azureボタンを押すだけでベンチマーカーのスケールアウトが実現できるようになりました。
システムの構成はざっと以下のような感じです。
[ユーザー] -enqueue-> [競技Portal] <-> [worker群] -benchmark-> [対象サーバー]
ワーカーの滞留の監視
ベンチマーカーの仕組み上、ベンチマーカーが結果の投稿に失敗することがまれに起こりえるようになっていました。それをMackerelで監視し、アラートを運営Slackに流すようにしました。それが以下の様子です。
アラートを検知をトリガーに手動でデータ修正をおこない(これはダサい)、復旧している様子です。
キューの状況のモニタリング
キューの状況を注視し、必要に応じて、ベンチマーカーノードの追加をいました。面白いのでグラフ画像を共有します。下の黄色い部分が稼働中のジョブの、紫の部分が待っているジョブの数になっています。最初は5ワーカーくらいから始まり、最後は20ワーカーくらいになっているのがわかります。
- 初日
- 二日目
実行ジョブの数
これはモニタリングとはあまり関係ないのですが、実行が終わったジョブのグラフも面白いのでお見せします。初日は7000弱、二日目は8500程度のベンチマークが動いたことが見て取れます。
- 初日
- 二日目
ワーカー群のCPU利用率積み上げ
これもちょっと面白いのでお見せします。初日と二日目で傾向が違うのが面白いですね。初日は競技開始後にバタバタしていますが、二日目は競技開始直後は穏やかで、その後、各チームがサーバーのセットアップが終わったくらいのタイミングで少しスパイクしているのがわかります。実際二日目のチームのほうがAzureをしっかり予習してきたチームが多かったように感じました。
- 初日
- 二日目
予選実施
予選当日はとにかくハラハラしました。初日はだいぶ精神的にも実際もバタバタしたのですが、二日目は多少は余裕を持って運営できたように感じています。二日目は、ランチを外に買い出しに行く余裕もありました。運営自体は、wtatsuruと僕がメインでやりましたが、pixivの面々も当日運営部屋にいてくださったのはだいぶ心強かったです。
参加者の皆様も、運営の至らない点がありながらも、丁寧に質問や問い合せをしてくださり、心苦しく感じるところもありましたが、非常にありがたかったです。問題もそれなりに評価していただいて、本当に嬉しかったです。
終わってみると、ほんとうに感謝しか無い。無事に終わってよかった。
とにかくしんどかった。けど良かった
作問中は、下手な問題を出すと、もしくは出題を落とそうものなら業界の信用を失うんじゃないかと不安で仕方がなかった。一般的に問題解く人よりもスキルが上の人が問題を作るものであるはずなのに、なんで自分より圧倒的にスキルが上の人に対して問題を作るのか意味が分からないよ、とか思ったりもしてた。
自宅で作業をする時は、本当に呻き声を上げながら作業をしていた。去年は色々忙しいことが多く、それぞれ辛くなることも多かったので、妻が僕の呻き声ソムリエになった。具体的には、僕の呻き声を聞き分けて僕が何の作業をしているか分かるようになった。例えば以下のような作業。
- ISUCON6予選作問
- 仕事(Mackerel好調なのでやることが無限にある)
- みんなのGo言語執筆
- マンション購入関連
まあでも良い体験になったのでこういう経験をさせてもらえたことは本当にありがたく思っています。終わって本当に良かった。
謝辞
本当に多くの皆様に協力していただきました。改めて感謝いたします。
- 引き継ぎ: tagomoris
- 問題アイデア出し: Songmu/motemen/wtatsuru
- コンセプト実装: motemen
- 初期参考実装: Songmu
- 競技ポータル作成: motemen
- ベンチマーカー及びワーカー: Songmu
- 予行演習解答: edvakf/catatsuy/walf443/st-cyrill
- Azureアドバイザリ: myfinder/(matsuu)
- インフラ及びプロビジョニング整備: wtatsuru/y_uuki
- 言語移植
- Go: y_uuki
- Ruby: aereal
- Scala: tarao
- Python/Node: walf443
- PHP: st-cyrill
- 予選当日のシステム運用・監視: wtatsuru/motemen/Songmu/myfinder
- その他予選当日サポート: edvakf/catatsuy/walf443/st-cyrill/y_uuki
- 採点: wtatsuru/Songmu
- アナウンス全般: 941
- 参加者の皆様
ISUCON7
てことで、今年は気楽に参加させてもらおうと思っています。純はてなチームで出ようと思っているので、それで優勝するのが目標です。今年の運営の皆様よろしくおねがいします。がんばってください!