ISUCON7 にチーム「スギャブロエックス」で参加して5位でした。
ベストスコアが29944点なので、せめてこれを最終スコアにしたかった…!
チームメイト
リポジトリ
所感
今回は "Chair Constructor Online" という ロジックが超複雑でサーバーのCPU負荷の高いリアルタイムオンラインゲーム ということで、非常に面白いテーマでした。BigIntが核心だったのもよくて、いちソフトウェアエンジニアとして地力を試された感じでした。運営の皆さん大変おつかれさまでした。
チームとしての動きはだいたいすぎゃーんが書いたとおりなので、ほかにいくつか特筆すべきことを私の視点から書きます。
NodeJSを選んだことについて
予選とおなじくNodeJSでした。
問題設定がWebSocket + BitInt だったのでNodeJSとの相性も悪くなさそうだし、予選でチームメンバーもNodeJSにある程度慣れたと思われるので問題はないだろうというところです。NodeJSでBigIntを触ったことがなかったのでライブラリを確認したところ、gmpの薄いラッパーだったのでこれも問題はないだろいうという判断でした。
https://github.com/kdawes/node-bigint
もっともこの実装は npmjs.org にリリースされていないようで、pakage.jsonのなかでrepository直指定でした。nodejs界隈ではあまりBigIntは使われないのかもしれないですね。
ちなみに tc39/proposa-bigintがstage 3でV8での実装も進んでいるようなので*1、来年くらいになればNodeJSでBigIntも普通に(あるいは --harmony-bigint
付きで)使えたのかもしれません。スコアには大きな影響はないでしょうが、四則演算子を普通に使えるのでコードを書くのは楽だったはず。
TypeScript化
すぎゃーんとkazeburoさんが計画を練っているときに私がコードをTypeScript化しました。コード自体は一瞬でできて、ついでにdeploy時にコンパイルしたりする仕組みも作ってミッション完了。30分くらいでできたと思います。
ESLintとTypeScriptどちらにするか悩んだのですが、変換さえしてしまえばTypeScriptのほうが書き味がよいこと、変換作業は直近でも何度かやっているのでそれほどハマらずにできる自信があったこと、などからTypeScriptを推すことにしました。
実際わりと好評だったと思います。
全体のストラテジ
2コアを活かすためにnodejsサーバのプロセスを増やすというタイミングで、kazeburoさんからは「systemdのサービスを2つ作ったほうがいいと思う」といわれたのですが、「面倒なので一旦cluster化します!!」という判断をしてしまいました。そして後にこれが大失敗だったなと思うにいたりました。
今回はroomごとにデータが完全に独立しているので、1サーバにウェブアプリとMySQLを同居させるという構成で分散させています。ここで最初は1サーバ1アプリプロセスだったので、他のroomとデータが干渉せずmutable dataでも安全にメモリキャッシュが行える状態でした。
ここでさらにnodejs1とnodejs2がそれぞれ別のポートをlistenすれば、そのアプリプロセスのなかでメモリキャッシュができたわけです。しかしclusterだとどのように分散するか不明なので、適切にパージが必要なmutable dataをキャッシュできません。なのでメモリキャッシュがimmutable dataに対してしかできないという制約があるまま最後までいくことになってしまったのでした。これは完全に私のやらかしです。ここでめんどくさがってはいけなかったのだ…。
NodeJSのプロファイラ
これは完全にNodeJSを選んで失敗だったのですが、なんとプロファイラが使えませんでした。正確には、プロファイルデータは出せるものの整形コマンドが数十分まっても戻ってこないため、結果をみれませんでした。
なのでCPU時間については測定せずに最適化するという苦しい戦いでした。これについては別途しらべないといけないですね…。
全体
予選・本戦と大変楽しく過ごせました。バランスの良いチームだっただけに、優勝できなかったのは残念極まりない…!!
来年は問題の移植作業を手伝いたいので参加はしないつもりですが、またいつかこのチームで本戦に参加できたらと思います!