ファイルI/O

このシリーズで初回のタイトルを「node.jsとの出会い」としたわけですが
そこには別段意図はなく、言葉の通りnode.jsとの出会いを綴ったわけですが
アクセス解析を見ていて、あるキーワードから当ブログに来ている形跡があり
そのRefererを辿るとちょっと引きましたね。
そんなキーワードで検索している人、本当にいるんだなと。

気を取り直して、今回はファイルI/Oについて。

そもそも、当ブログではまだ触れていなかったですがnode.jsは直列処理をすることが特徴です。

「C10K問題」と言うフレーズを聞いたことありますでしょうか?
恐らくサービスを運用しているところではないと、なかなか聞きなれないのかもしれません。
あるいは開発者でも運用面まで考える立場の技術者など。
詳しくは↓

つまり並列処理をコントロールする側の論理的な限界があるようです。

node.jsは直列処理をすることでその問題をクリアしてます。

これは良くレジに例えられますが
複数台のレジカウンターを並列に運用するのが今までのウェブ処理だとすると
node.jsは1台のレジカウンターで処理する。
その1台は高速に動く。そんなイメージだそうです

リクエストからレスポンスをイメージにするとこんな感じでしょうか。
従来のイメージ
従来のイメージ

node.jsのイメージ
node.jsのイメージ

実際はどれだけの速度で処理するのかによるのでしょうが、それは同じ条件だとすれば
これだけ見ると「Wait」が多いからあまり効率的じゃないですよね。

相変わらず前置きが長いですが、そこで今回の議題でありますファイルI/Oの話が出てきます。

リクエストに対して、サーバサイドプログラムが処理をするパターンケースはそう多くないと思います。
私が知らないだけかもしれませんが
当然ただの静的ファイルの返却はウェブサーバが返却します。
そうではない場合は、PHPやPerlなどのプログラムが
受け取ったリクエストに応じて、ファイル、データベース、メモリに対してI/Oをし
その値に対して何かしらの演算が生じるだけではないでしょうか。

つまり「Wait」が生じてしまう原因として、過去のリクエストで実行しているデータI/Oにかかる時間が主だと思います。

これに対して、上記の図のようにならないよう
node.jsはI/O部分を別プロセスで実行し、そこから返却があるまで別のリクエストを受ける事ができるようです。
イメージにすると
node.jsのイメージ2
こんな感じでしょうか。
このように、要件によるのでしょうが「同期」をとる必要のある処理にも対応でき
そうではない「非同期」としてもnode.jsでは実行できるようです。

これをプログラムとして書くと

require('fs');

var path = 'ファイルパス';
var data = fs.readFileSync(path);
console.log(data);
console.log('END');
require('fs');

fs.readFile(path, function(err, data)
{
	console.log(data);
});
console.log('END');

こんな感じです。
なるほど、こうすることでスーパーバイトのレジマスターが千切っては投げ千切っては投げが出来るんですね。
実際サンプルを用意して速度測定まではしませんが、なんだか高速に動き気がしてきました。
それが気のせいなのかは、実際にシステムを運用してみて体感する機会が来るかもしれません。