2011年2月20日日曜日

node.jsは普及しそうに無い

このエントリーをはてなブックマークに追加
Pocket

ここ一ヶ月ぐらいからJavaScriptが注目されているようだ。理由は簡単で、GoogleのJavaScriptエンジンを使ったアプリケーション・サーバーであるnode.jsの性能が高いと主張されているからだ。

地味にブームになりつつあり、Ajaxのようにウェブ開発の現場に定着するかも知れない。多数のブログで紹介がされている。現状のその特徴を振り返りつつ、node.jsが普及するかを考察してみた。

1. JavaScriptは、ブラウザ発の人気スクリプト言語

JavaScriptは、LiveScriptとして1995年にNetscape Navigatorというウェブ・ブラウザに搭載されたのが始まりで、すぐに政治的な理由でJavaScriptに改名された。1996年には、その基本的な文法がECMAScriptとして、ECMA-262とISO/IEC 16262で定義されている。言語仕様が簡潔かつ柔軟と言う事で、概ねプログラミング言語としての評価は高い。

ECMAScriptとして見ると、応用範囲はブラウザに留まらず、WindowsではJScriptとしてバッチ・ファイルとして利用する事もできるし、PDF内でフォームを制御する事もできるし、Flashの制御スクリプトとしても応用されている。C、C++、Javaの実行エンジンが以前から公開されており、JavaやC++アプリケーションに内蔵させる事も容易である。最近のバージョンのJavaやQtでは、実行エンジンが標準ライブラリとして添付されている。

2. I/Oの欠如がブラウザのJavaScriptの制約だった

ブラウザ内のJavaScriptに限定すると、利用範囲の広さの反面、互換性やJavaScriptアプリケーションの高度化には長い間、失敗していた。正規表現なども使えるようになり、JavaScriptの機能性はあがっていたのだが、セキュリティーの問題もありファイルやネットワーク入出などのI/Oが無い状態が続いたからだ。

処理するデータが読み込めず、処理結果を保存できないのであれば、プログラミング言語の魅力は半減してしまう。登場から5年以上の間、ウェブ・アプリケーションでJavaScriptは補助的な位置づけを超える事は無かった。

3. Ajaxで復権したブラウザのJavaScript

しかし、I/Oの欠如はMicrosoft社のInternet ExplorerがActiveXObjectで解決し、他のブラウザがXMLHttpRequestで追随し、Jesse James Garrett氏がAjaxとして応用方法を世間に提示して概ね解決された。つまり、JavaScriptファイルのダウンロード元のサイトとJavaScriptが、httpでの通信ができるようになったわけだ。これはJava Applet程度の機能でしかないが、大量に存在するJavaScriptプログラマと相乗効果を発揮して人気の手法になった。

4. フレームワークによるブラウザJavaScriptの互換性の向上

ブラウザ戦争と呼ばれたNetscape NavigatorとInternet Explorerの独自拡張の結果、JavaScriptのライブラリには互換性の問題が多かれ少なかれ存在する。オブジェクトの存在確認が可能であるため、両方に互換性があるコードを作成することは難しくは無いが、意識してコーディングを行うのは煩雑であった。しかし、2005年からprototype.js、2006年からjQueryと二つのJavaScriptフレームワークが開発され普及したため、ブラウザ間の互換性は以前よりも意識しなくても良くなっている。

5. JavaScriptの実行速度の高速化

ブラウザでのJavaScriptの利用拡大は、JavaScriptの実行エンジンの速度競争を引き起こした。Firefox 3.5で搭載されたTraceMonkeyや、Google Chromeで搭載されたV8は、他のスクリプト言語と比較しても圧倒的な速度を誇る。V8はPHP5.3比較で10倍以上、TraceMonkeyは約8倍の速度をベンチマークで記録しており、現状では最速のスクリプト言語はJavaScriptになっている(The Computer Language Benchmarks Game)。

6. サーバーサイドJavaScriptの突然の注目

GoogleのJavaScriptエンジンV8を使ったアプリケーション・サーバーであるnode.jsがリリースされた後に、サーバーサイドJavaScriptに注目する人が増えた。

Microsoft社のウェブサーバーIISでは、JScript(Microsoft社方言のJavaScript)が1997年から動く。その互換Apacheモジュールとしてmod_jsが存在するため、今までもサーバーサイドでJavaScriptを動かす事はできた。その意味で、サーバーサイドJavaScriptに目新しい点は無い。

しかし、潜在的なJavaScriptプログラマの数が増加したため、従来よりもサーバーサイドJavaScriptへの期待が高まりやすくなっているのだと考えられる。

7. マルチスレッド・モデルの限界、C10K問題

node.jsが注目を浴びた理由には、C10K問題が背景にある。

同時接続数が増加すると、従来のウェブ・サーバーは著しくパフォーマンスを落とす傾向がある。これをC10k、クライアント台数1万台問題と言う。人気のウェブ・サーバーApacheは、バージョン1.3までのマルチタスクから、バージョン2.0以降のマルチスレッドに進化することで改善はしたが、それでも同時接続数が1,000にもなるとパフォーマンスが悪い。

同時接続数が1,000を超えるサイトは、そこそこの人気サイトではある。しかし、Ajaxが一般化し、Twitterのように定期的にサーバーに通信を行っている場合があるので、サーバー側の負荷が高まる傾向にある。また、旧世代のPDC携帯電話からアクセスされると、通信速度の問題で、同時接続数が飛躍的に上昇するケースがあった。

8. C10K問題を解決を期待されるnode.js

node.jsはGoogle V8 JavaScriptエンジン上で動く、TCPサーバー・フレームワークだ。イベントループ・モデルで処理を直列化することで、メモリ利用量を抑えプロセス/スレッド間の競合を防いでいる。Windows 3.1風のノンプリエンティブなマルチタスク・モデルだ。

現状ではhttp/https、そして低レベルTCPをサポートしている。CやC++でモジュールを書く事も容易であり応用範囲は広いが、現在は同時接続数が多いときのスループットが注目されている。

Apache(mod_php)と比較したベンチマークが多数出ているが、概ねパフォーマンスが良い。 同時接続ユーザー数が100未満だと余り効果が出ないようだが、500を超えたあたりから徐々にパフォーマンスが悪くなるApacheに対して、node.jsはパフォーマンスを維持できるようだ。

以下は、Node JS vs Apache PHP benchmarkの転載だが、同時接続数800でnode.jsとApache(mod_php)との差が大きくなっている。

なお接続数が400以下の差は、主にPHPとJavaScript(V8)の実行速度の差に起因すると思われる。

9. node.jsの問題点

高負荷時のパフォーマンスが優れているのは確かのようだが、現状では次のような欠点もある。万能薬的な使い方は出来ないようだ。

  1. イベントループ・モデルで処理を直列化しているので、あるリクエストの処理に時間がかかる場合、他の全てのリクエストをブロックする可能性がある。
  2. イベントループ・モデルで平行処理を行わないため、複数コアを持つCPU/MPU、複数のCPUを使うSMPでパフォーマンスの上昇が、JavaScriptのコード部分は期待できない。
  3. JavaScriptのプログラミング言語としての限界が影響する。つまり、オブジェクト指向が不完全であること、動的型付けでJavaやC#に対して速度面に限界があること等が、大規模で複雑なアプリケーションには影響を及ぼす可能性がある。
  4. あるページを表示するためのサーバー側のJavaScriptの文法エラーが、サーバーの停止を引き起こす。簡単なプログラム・ミスが、アプリケーションの非クリティカルな部分に発生したとしても、システム全体がダウンする結果となる。
  5. 非同期化によるパフォーマンス向上がイベントループ・モデルに依存するため、イベントを受けるコールバック関数が多くなり(単純なファイル操作でも3回コールバックが発生する)、ソースコードの見通しが悪くなる。
  6. 利用可能ライブラリが限定的であり、開発支援ツールが無い。Apacheモジュールも種類や用途が多いし、JavaやPHPにも覚えきれないほどのフレームワーク製品群とライブラリがある。これらに依存しない用途にしか、現状では利用できない。

追記(2011/02/20 19:50):コメントで(1)に関して疑われているので、実証コードにリンクしておく。

追記(2011/02/20 21:20):(4)に関して例外をキャッチすれば継続稼動可能と指摘があった。コード中に例外を正しく拾わないと中断する点は変わらないが、動作を継続するようにはできる。

追記(2011/02/20 21:30):(2)に関して、複数プロセスでロードバランシングを行いマルチコアでのパフォーマンスを向上させるツール/ライブラリが出ていると指摘があった(fugue、Spark2、cluster)。これらを組み合わせる事でパフォーマンスの向上が期待できる。

上記二つを御指摘頂いたページには他にも指摘事項があったので、node.jsに関心が強い方は閲覧することをお勧めする。

10. レスポンスに潜在的な問題を抱え、遅い状況もある

(1)について補足する。node.jsファイルやデータベースなどのI/O入出力は非同期化され、処理が完了するとイベントが発生する。しかし、I/Oへ出力するデータを作成したり、I/Oから入力したデータを処理するのは、JavaScript側になるため実行順序が直列になり、重い処理が軽い処理を容易にブロックする。

node.js以外の大抵のApache(mod_php)やTomcat(Java)などのサーバーは、リクエストごとにスレッドを分けて処理するため、この問題は発生しない。

また、(2)や(3)を考慮すると、node.jsのパフォーマンスが優れているとは言い切れない。従来型のソリューションの方がパフォーマンスが出るケースも多々あるはずだ。近年は4コア、8コアのサーバーが安価に入手でき、ハイエンドPCサーバーでは8プロセッサで64コア構成になっているものもある。

11. node.jsは諸刃の刃で、一般用途では使いづらい

総括するとnode.jsは、比較的均質な計算量の処理が走る単純なベンチマークだとパフォーマンスが良くなるが、リクエストによって計算量が大きく変化する場合は、現状では応答速度に問題が出るケースが出てくる。

フレームワークやライブラリの充実度、習熟プログラマの数、ノウハウの蓄積、ハードウェア構成の柔軟性を考えると、PHPやJavaを置き換える可能性は少ない。また、パフォーマンス不足に悩まされているサイトは少数で、悩まされているときも同時接続数が問題であるとは限らない。

node.jsに注目している人々が、イベントループ・モデルの問題点を検証した形跡も無いので、本気で利用する気がある人は、ほとんどいないように思える。Google Trendでnode.jsの検索数を確認してみたが、2010年10月と2011年1月に間欠的に検索数が増加しただけであった。

5 コメント:

mjh さんのコメント...

> Windows 3.1風のプリエンティブなマルチタスク・モデル
Windows 3.1風というのであれば非プリエンプティブ ということですか?

uncorrelated さんのコメント...

>>mjhさん
ノンプリエンティブですね。訂正しておきました。

Nariya Takemura さんのコメント...

http://www.google.co.jp/trends?q=node.js

指摘するのも野暮ですがGoogle treds, 今の時点ではまだ増加中な気がします

uncorrelated さんのコメント...

>>myr さん
これは2月20日に書いた記事なのですが、その後も関心は持たれているみたいですね。

http://www.google.co.jp/trends?q=node.js&ctab=0&geo=jp&geor=all&date=2011&sort=0

日本だと平行線で、米国だと2~3倍といった検索数です。海外ではnode.jsにあった需要があるのかも知れません。

匿名 さんのコメント...

node.jsのドキュメント見ましたが、cluster関連のモジュールを使えば、負荷分散みたいなことができるようです
http://nodejs.jp/nodejs.org_ja/api/cluster.html
Cluster

コメントを投稿