#Node.js とは
- Node.jsはChromeのV8 JavaScriptエンジンをベースに作られたJavaScriptランタイムです。
- Node.jsはevent-driven、non-blocking I/O modelデザインなので軽量で効率的です。
Blocking vs Non-Blocking
この二つの違いは、リソースをプロセスに集中すべきか否かです。
Blocking (synchronous)
このオペレーションを処理する場合は、そのプロセス処理を終了するまで次のオペレーションに移ることが出来ません。
例えば、お茶を飲むという行動はBlockingオペレーションです。
1. カップを口までは運ぶ 2. お茶を飲む 3. カップをテーブルに置く 4. 完了
お茶を飲んでいる間は、お茶を飲むことに集中していると思います。
Non-Blocking (asynchronous)
このオペレーションを処理する場合は、とりあえずプロセス処理を開始します。
I/Oオペレーション等でリソースを使わない割に時間がかかりそうだったら、一旦そのスレッドを保留して、他のスレッドのプロセス処理に移行します。
保留していたプロセスの処理が完了した、良いタイミングでそのプロセスに戻ってくることが出来ます。
例えば、お茶を沸かすという行動はBlockingオペレーションです。
1. お茶にお湯を注ぐ 2. 数分待つ 3. お茶をテーブルまで運ぶ 4. 完了
お茶の完成まで、お湯を注いでから数分は自由な時間が出来るます。
その間に、テーブルを片付けたり、テレビをつけたり出来るはずです。
JavaScriptはシングルスレッド言語
##スレッドとは
CPUのコアが処理するプロセスのQueue的なものです。
CPUサイクル毎に処理できるスレッドの数は、物理的なコア数に比例しています。
よって、CPUのコア数が4つの場合は
CPUサイクル毎に4つのスレッドを処理することが可能です。
##シングルスレッドとは
マルチスレッドの対義です。
JavaScriptの場合は言語のデザイン上、複数のスレッドを管理する機能がありません。
なので、すべてのオペレーションは一つのスレッド上で管理されています。
##Node.js = non-blocking I/O model
しかし、asyncオペレーションを行うのには、複数のスレッド管理が必要です。
ではどうやってNode.jsはasyncオペレーションを行うのでしょうか?
答えは Node.jsのコア、イベントループです。
イベントループ とは
JavaScriptがシングルスレッド言語であるにも関わらず、Node.jsが non-blocking I/O オペレーションを行える仕組みです。
##大まかな仕組み
スレッドの管理をJavaScript自体で行わず、カーネルにお願いする感じです。
カーネルがnon-blocking I/Oオペレーションを完了すると、Node.jsに終わったよーと教えてくれます。
そしたら、Node.jsは対象のcallbackを実行します。
##もう少し詳しく
Node.jsのプロセス開始と同時に、イベントループも開始します。
- timers: このフェーズでは、
setTimeout()
やsetInterval()
でスケジュールされたcallbackを実行します。 - pending callbacks: 次のイタレーションの I/O callbacksを実行します。
- idle, prepare: 内部ロジックのみで使用
- poll: 新たな I/O イベントを取得; I/O関連のcallbacksを実行; 必要であればここでオペレーションのブロック。
- check: setImmediate() callbacks はここで実行されます
- close callbacks: socket.on('close', ...)のようなcallbackがここで実行されます。
参照
https://nodejs.org/de/docs/guides/blocking-vs-non-blocking/
https://nodejs.org/de/docs/guides/event-loop-timers-and-nexttick/
https://blog.logrocket.com/a-complete-guide-to-the-node-js-event-loop/