JavaScript
Node.js
isucon
isucon7

ISUCON7予選のNode.js参考実装を担当させていただきました

More than 1 year has passed since last update.

ISUCON7のNode.js版の参考実装の作成を担当させていただきました。
参加者のときとは全然別視点で、得られたことが沢山ありました。
Twitterでもつらつらと書いてたのですが、まとめた振り返りを書きたいと思います。

なお参考実装のリポジトリはこちらからご確認いただけます。

ISUCON7 予選問題の公開と解説 : ISUCON公式Blog

自分のISUCON歴

ISUCON5, 6と二回参加し、どちらも予選敗退してます。
ちなみに過去二回ともGoでの挑戦で、Node.jsで挑んだことはありませんでした。

なぜやったか

自分は参加メンバーを集めきれなかっため、
Node.js版で参加したいという知り合いから「Node.js版に清き一票を!!」と推されて一票入れ、
あとは今年のISUCONには関わらず終わりかなと思っていました。

でしたが、ある日Twitter見てたら偶然TLに流れてきて、

普段仕事でJS書いてるので、Node.jsならお役に立てるのではないか?
というか、やるしかない と速攻で申請出し、運よくNode.js版の担当にしていただきました。

これまでにつながりやご縁は全くなくて、私のことを誰も知らないでしょうし、私も中の人が誰なのかを知らなかったのですが、チャンスだと思ってえいやで飛び込んでみました。

なにをしたか

Node.js版で挑んでいただいた方はお分かりかと思いますが、
Node.js6.x系の最新+Express+Promiseベースの一昔前(?)のNode.jsっぽいコードだったと思います。
Node.js8.x+Koa+async/awaitも検討していたのですが、あえて古い側に倒しました。

バージョンやF/Wについては、コアメンバーの方にも相談させていただいて、安定で行くことにしました。
普段の仕事だとゴリゴリとバベっているので、ES7以前の書き方にやや手間取りました。

ISUCON勢の方々ならasync/awaitのコードも良いかも?とも思ったのですが、
8.xに追従してない方がいた時にNode.js固有の問題にハマってしまうのはよろしくと思い、LTS入っている6.xと、たぶん最も使われてるNode.jsのF/Wに倒しました。
(もし来年もISUCONがあって、Node.js実装があるなら、その頃にはasync/awaitでいいのではないかと勝手に思っております。)

どうしたか

実装は、基本的にはすでにある参考実装をベースに、Node.js方言に翻訳して行く作業という感じでした。
言うまでもなく非同期処理が大半なので、他の言語とは書き方がだいぶ異なっています。
例えば、ループ回しつつクエリ打つところを他の実装と合わせるところはPromiseで数珠繋ぎにして直列並びにしてました。

基本的に必要なメソッドはpromisifyしてPromiseで繋いでいくという実装にしたのですが、
ExpressだとPromiseがとにかく扱いにくく、エラーハンドリングでかなり苦戦しました。
Promise捨てて昔懐かしコールバック地獄にするか悩んだのですが、そこまで行くと読みにくさが自分の許容値を超えていたので、Promiseで統一してあの実装に至ります。

他にはDBのコネクションをリクエストのたびに都度接続方式にしてしまうと、タイムアウトで切断されたコネクションが残ったまま、どんどんリクエストを裁こうとしてしまうのでToo many connectionsが起きまくるなどといった、リクエストのハンドリングやコネクションの管理は、書いてみてかなり難しかったです。
結局不安定な動作を拭きれなかったので、最大接続数で絞ってプールするよう安定側に倒しました。

ちなみにトランザクションなかったのでこの方式でいけましたが、
もしトランザクションが必要だったら、プールに対してクエリを打つのではなく、プールから接続を1つずつ取り出してリクエストの間使い回す、という実装が必要でした。

いつやったか

実装量はそんなになかったので、普通に仕事しつつ、仕事終わりにちょこちょこやってました。
出した実装は何度もベンチにかけられ、安定性などの面で多数ご指導いただいたり、レビューしていただきつつ、予選に余力を持って間に合うくらいのスケジュール感でやってました。

寝る間も惜しむ程ではなく、ふつうに仕事しながらやれるぐらいの負荷だったと思います。

なにを得たか

他の言語担当の方やコアメンバーの方々は、名前を聴いたことがある方や登壇してるのを聴講者として聴いてたことがある方々だらけで、場違い感を感じ萎縮してました。
が、自分がNode.js担当なのできちんと仕上げなければと思い、相当お助けしていただきながらも予選に使ってもらえるものにできてよかったです。

  • 面識のない方にレビューしていただくの初めて
  • パフォーマンス悪いけど安定したアプリケーションづくり難しかった
  • レビューの観点が本質的で鋭くて、自分がレビューする時も気をつけたいと思った
  • 認証周りものすごい初歩的なところでご迷惑おかけした。。
  • バグ発生時の問題究明に到るまでの速度がめちゃくちゃ早い。作った本人(私)より早く突き止めていただいたり。
  • ベンチマークのコードがえげつない量しっかり書かれていて、テスト書くときに真似したいと思った。

などなど、他にも刺激がたくさんありました。PR1つ1つ勉強になったと思います。
まだまだ実力も経験も足りず、精進しなければと痛感しました。

予選お疲れ様でした!!!

参加者の方も運営の方も他の言語実装の方も、みなさまお疲れ様でした!!!
特に運営の方々には大変お世話になりました!とても勉強になりました。
当日会場に行けずすみませんでした。無事予選が終わってよかったです。

参加者になれなかったので、(ネタバレも見ちゃったのですが、)自分で作ったNode.js版でぼっちISUCONやろうと思います。
(予選突破のスコア高すぎて、ネタバレ見ても時間をかけても届く気がしません...)

最後に

ISUCONからは学んでばかりだったので、今回の参考実装づくりでISUCONに少しでも貢献できていたら嬉しいです。
「Node.js実装あるから出場した」「Node.js実装あるなら試してみようと思った」とか、何かしらISUCONへの動機づくりの助けになれていたら幸いです。

ISUCONの参考実装づくり、とても勉強になったので、
もし次回(あるのかな?)も募集がかかったら、ぜひ実装者として手を上げてみてください!!