2011-04-04

あるライブラリのおもいで

そういえば先に紹介した本のサンプルコードは 前勤務先が開発していたライブラリを使っている. そんなのがあったなと思いだした. 開発元の会社は私が退職したあと解散してしまい, 製品としてのライブラリもなくなってしまったようだ. 少しはバグとりなどを手伝った身として一抹のさびしさがある. 今は亡きこのライブラリを偲んでみたい.

それは C(v1.x)/C++(v2.x) で書かれたノンブロッキングスタイルの通信ライブラリで, libevent に類する イベントシステムと IO を抽象化するレイヤの上に バッファ管理, フレーミング, 多重化, 暗号化, 圧縮, UDP ベースのストリーム実装 と hole punching を実装し, 簡単な RPC もついていた. そのほかにも経路の heartbeat や素朴なリマッピング, 簡易チート対策, 高負荷な暗号化や圧縮だけを別プロセスに切り離すプロキシや など細々とした機能もあった. 暗号化や圧縮にはサードパーティのコードを使っていたけれど, ゲーム機をサポートする都合などから I/O のラッパは自分でコードを持っていた. 内製向けに Flash と Python のバージョンも書かれていた.

ノンブロッキングスタイルの良さ

ノンブロッキング/非同期のプログラミングスタイルはゲームと相性がよい. 伝統的なつくりのゲームはコードの中にいわゆる "メインループ" があって, 大ざっぱにいうと一回のループで 1 フレーム分の処理をする. 一秒に 30 なり 60 なりのフレームを描画する必要があるから, 1 フレームあたりに使える時間は限られる. だからファイルなどの出力は自然と非同期になる. 同様に非同期通信はほとんど不可避だったし, 実際よく馴染んだ. キー入力を読むようにパケットを読めばいいからね.

サーバ側には select() などシステムコールからの通知を処理するイベントループがある. このループの上でタイムアウトや状態変更のバッチ化を工夫し "フレーム" に似た概念を作れば, サーバのコードにも普通のゲームプログラムに近いパラダイムを持ち込むことができる. 要するにサーバのイベントループがゲームのメインループになる. ループの中でフレーム毎に時間を進め, イベントを処理すればいい. 故ライブラリはこの辺にも少し工夫があった.

件の本ではノンブロッキングの利点に スレッドモデルの簡素さやオーバーヘッドの少なさを挙げていた気がするけれど, 私個人はプログラミングモデルの馴染みの良さが決定的な利点だと感じていた. (同様に C++ を使うのも性能以前にゲーム開発会社の人材分布や クライアント側プログラムとの親和性が大きな利点だったとおもう.)

デザインと機能

故ライブラリ開発元での最初の仕事はこのライブラリのバグとりだった. まずドキュメントとコードに目を通した私は... API デザインのひどさに驚いた. これをよしとして対価を払ってくれる顧客がいたし私の好みにもだいぶ偏りがあるから, ひどいというのはフェアでないかもしれない. ただ現代的なデザインではなかった.

一方で機能の取捨には唸った. API にがっかりした私はオープンソースの代替品を探していたものの いまひとつ良い候補が見当らず, その事実が機能定義のうまさを私に知らしめた.

通信のレイヤでは Java の MINANetty が近い性格を持っている. ASIO のようにテンプレート原理主義でなく 実行時多態で拡張しやすい C++ 実装があればあれば足がかりになったかもしれない. RPC は Thrift はじめ色々な実装があるけれど, 概してノンブロッキングに優しくなかったし, チート対策をはじめとするゲーム固有の細々した機能, コードサイズやマルチプラットホームなど, 他にない特徴はことさら代替が難しかった.

オンラインゲームの通信に伴う問題と解決方法を, ライブラリの書き手はたしかに理解していた. ただそれをライブラリに符号化する方法がまずいように見えた. 実際, よりアプリケーション層に近いコンポーネントの再利用は 複雑さの bankruptcy によりほとんど失敗していた.

一方の私は C++ のコードがどうあるべきか(相対的には)知っていると感じていたけれど, 要素技術たるネットワークスタックの難しさをわかっていなかったし, オンラインゲームの領域に至ってはまったく無知だった. 自分がそのライブラリに口を挟み書き直したところで ピントのずれた自己満足のゴミにになるのは間違いなく, 何もできなかった. 語りの言葉を欠く書き手に苛立ちながら, 語るべき物を持たない身にはずっと後ろ暗さを感じていた.

My Favorite Vaporware

ネットワークスタック, ゲーム, コードの再利用性や抽象, それぞれをきちんと理解した誰かが書けば, この分野の良いライブラリができるだろう. そういうものがあるなら触ってみたい気はする.

昨今隆盛にあるソーシャルゲームなるゲームのバックエンドは, 多くが単なるウェブのシステムに見える. (ちがったらごめんなさい.) でもたとえばコンシューマゲームの企業が参入して競争がおき, その果てにリアルタイム性の高いゲームが流行ることになれば, おそらくもう少し面倒なコードも書かざるをえなくなる. そんなコードのためのライブラリが求められる日は来る...かもしれない.

いつかそうした仕事(趣味も可)をされる皆様におかれましてはぜひ EventMachine, Tornado, Node.js, Netty といったノンブロッキング IO の上で サーバを書いていただき, クライアントは iOS, あんどろ, Flash から ブラウザまでサポートされた上でクロス言語の RPC を載せ, 野次馬 明るい日本の未来のため ライブラリにパッケージングしオープンソースでリリースしていただければと思います.

あらあらかしこ... あとできれば非同期 ORM もほしいです.