node.js と thread hog の話(1)
2012.10.15
ここ数日、 node.js で色々と作りはじめているのだが(node.js が一番力を発揮するのは、xmpp server や、push notification server のようにソケットを開きっぱなしにして非同期通信をするケースだと思うのだが、それについては来週のメルマガで詳しく解説する)、これで思い出すのが Microsoft 時代の「"thread hog" 退治」だ。
"thread hog" とは私が作った造語で、"memory hog" (メモリをやたらと使うプログラムのこと)と同じように、thread を不必要に作るプログラムのこと。
最初に出会った thread hog は、Microsoft が作っていた proxy server だった。コネクションが1000を超すとやたらと遅くなり、しまいには落ちてしまうという欠点を持っていたため、一時は「出荷出来ないところか、社内でも使えない」と大問題になっていた。たまたま担当者が知り合いだったので、理由を尋ねると、コネクション1つあたり1つの thread を使っており、これが問題だと言う。
私はそのころちょうど、single thread の web server を作って (multi thread 派の)IIS グループとwebサーバーのあるべきアーキテクチャについて論争を繰り広げていたので、「これは良い機会」だと、担当者に非同期ソケットを使って single thread 化することを強くすすめた。彼も最初は懐疑的だったが、実際に試してみると驚く様にスループットがあがり、数千のコネクションを楽々とこなせる様になった。
次に出会った thread hog は、OLE (Object Linking and Embedding)だ。Windows 95 上で Excel の表の一部を Excel から Word に copy & paste するのにやたらと時間がかかるので、デバッグして欲しいとの要請が来たのだ。
調べてみると、OLE の中にある DCOM (Distributed COM)が、プロセス間通信のたびに thread を生成し、かつブロックしている。Excel から Word に copy & paste をすると Excel と Word がお互いの method を何重にも呼び合うため、たかが copy & paste のために thread が10個以上作られていたのだ。これも proxy server のケースと同じように DCOM のプロセス間通信の部分を大幅に書き直して、thread をブロックせずにすべて非同期 API で処理する様にして、大幅なスピードアップをはかることに成功した。
Exchange Server へのリモートアクセスを可能にする MAPI に関しても全く同じ問題を発見したが、これに関しては、Exchange グループは、私の進める MAPI の非同期化に猛反対をし、ローカルにデータベースの cache を作る、という方法で逃げた。Microsoft の MAPI が、インターネット・スタンダードである POP3 や IMAP に決して勝てなかった理由はここにあるのだが、当時の Exchange Server の連中は非同期APIをアレルギーのように嫌っていたので、どうしても無理だったようだ。
この経験を生かして、Web Server も single thread 化するというバトルを IIS グループに挑んだのだが、ここでも同じような激しい抵抗に会ってしまう。Web Server を single thread 化するということは、HTTP transaction の処理中のファイルシステムやデータベースへのアクセスも非同期APIを使わなければならないことを意味するが、「そんな面倒なことは開発者はしたがらない」というのが彼らの言い分だった。
そんな私から見ると、node.js のアーキテクチャはものすごく納得できるのだが、同時に「全てが非同期でなければいけない」という部分にアレルギー症状を示すプログラマーがいる理由も良くわかる。
しかし、CPU が1インストラクションを実行する時間と、ネットワーク通信をする時間(もしくはディスク上にあるファイルにアクセスする時間)は開く一方なのだから、この違いをプログラマーに見えないようにしよう、という発想自体が根本的に間違っていると私は思う。
(つづく)
Comments