Hatena::ブログ(Diary)

I am Bad at Math

2010-10-20

node.js とは何か

00:07 |

期せずして久々の更新になってしまった。ブログを書く気がなくなったとかそういうのではなくてただ単に忙しかっただけ。その間、まぁ仕事が予期せぬ方向から炎上してみたり、事故をもらって愛車が全損したり(フロントガラスが全面熱線入りなんていう変なオプションなどを諸々付けていたからお気に入りだったのに)と決して良いことばかりで忙しかったわけではないけどね!

で、今回は node.js のお話。異様な盛り上がりを見せているものの、じゃぁそれっていったい何かというと「JavaScriptを用いたNon-blocking I/O環境」という非常にシンプルなものだ。

その根底には「うまくスケールできること」と「動作が速いこと」という理念が見受けられる。

まず「うまくスケールできること(多量のアクセスを捌けること)」を解決するにあたり、まずはスレッドモデルか、イベントループかという問題があった。そこで author たる ryan は一つの決断をする。

「イベントループ」

node.js が生まれたのは 2009 年に入ってから。ちょうどそのころ C10k 問題がクローズアップされていてね、いろいろなベンチが公開されていたわけなんだけどウェブサーバの apache vs nginx といった構図のベンチもその中の一つにあったんだ。

この apache vs nginx のベンチが何を意味するのかと言えば先ほどのスレッド対イベントループ。apache はご存じのとおりスレッド、対して nginx はイベントループ。で、その性能の差は使用メモリ量などに端的に表れていたんだ。スレッドモデルの場合ね、実行スタックをコピーする必要があるからスレッドが増えるほどメモリ使用率が上昇する。対してイベントループモデルは1プロセスのままだからメモリはそれほど食わない。この点ではイベントループが有利っていうコンテクストだ。

ただね、イベントループモデルにも弱点がある。それはコードのどこかでブロックする処理が発生するとプロセス全体がストップしちゃう、つまりイベントループ自体の処理もストップしてしまい、パフォーマンスに大きく影響してしまうってことなんだ。

ryan はこの、イベントループにおけるブロックをなくそうと考えた。それが node.js のそもそもの始まりってわけ。

このブロックしてしまう処理というのはI/Oに端的に表れていて、たとえばCPUのL1キャッシュだと3サイクル、L2で14、RAMだと250で済むんだけど、それがDISKになると41,000,000サイクルかかって、ネットワークならさらに240,000,000サイクルもかかってしまうんだ。これがどのくらいすごいのかというと、サイクルをメートル換算してみるとわかりやすい。RAMでも250メートルでまだ目の届く範囲なんだけど、DISKになった瞬間、地球一周分、ネットワークだとさらに地球6周分!!!このコストの比はやっぱりトンデモナイんだよね。

で、ちょっと話はズレるんだけど、イベントループを利用したモデルっていうのは今までも他の言語で既に実装されていて、例えばPythonでいうとTwisted、RubyではEventMachine、PerlではColoのAnyEventなんかもある。ただそれらの実装ではNon-BlockingのI/Oを強制したりはしていないがために、スレッドで書かれた同様の処理をするプログラムよりも遅い場合があるんだよね。

だから Non-Blocking I/O の使用を強制してしまうことでさらなる高速化を図ろう、それが node.js なんだ。

この node.js の js に決まったというのはもともと JavaScript がシングルスレッドモデルでイベントループという仕組みを持っていたからで、だからもし JavaScript がスレッドモデルを採用していたとしたら node.js ではなくて node.el になっていたとしても不思議じゃなかった。

このJSの採用というのは大きな副次的効果を生み出すことになる。ウェブアプリに関わっていた人たちって大抵は多かれ少なかれJSを使っていたからね、新規の学習コストが非常に低い。つまりウェブアプリ開発者なら誰でも使えるような言語だってこと。

さらに具合のいいことにすでに Google V8 という、JavaのHotSpotにも携わっていた Lars Bak が生み出した高性能のJavaScriptバインディングがすでにあった。非常に嬉しいことにV8はC++環境に組み込みやすいという利点さえある。「動作が速いこと」という理念の一つにはこの V8 の影響力ももちろん欠かせない。

こうした結果として V8+Non-Blocking I/O が node.js として産声をあげることとなる。



唐突だけど、続きはまた明日なのだ。

車乗らないとついつい飲みに行っちゃうんだよね。飲んだら乗るな、乗らないなら飲め、みたいな。だから飲んでしまい眠くって先が書けないのである。

続き書きました。