Movatterモバイル変換


[0]ホーム

URL:


Uploaded byshigeki_ohtsu
PPTX, PDF28,450 views

そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解する

Related topics:

Embed presentation

Downloaded 119 times
そうだったのか! よくわかる   process.nextTick() Node.jsのイベントループを理解する   IIJ 大津 繁樹 (@jovi0608)        2012年6月28日     東京Node学園6時限目
Nodeの歩み(参考)2007/10 libev公開           2010/08 nodejs_jp開始2008/05 libeio公開          2010/09 no.de開始2009/09 Google V8公開       2010/11 Joyent管轄へ2009/02 ry Node開発開始       2011/02 node-v0.4.0リリース2009/05 node-v0.0.1リリース   2011/03 東京Node学園#12009/06 nodejs ML開始       2011/10 東京Node学園祭2009/10 npm公開             2011/11 node-v0.6.0リリース2009/11 JSConf EU ry発表    2011/12 Azureサポート2010/04 Herokuサポート        2012/01 isaacs管理へ2010/08 node-v0.2.0リリース   2012/06 node-v0.8.0リリース
今日の話•   Nodeのイベントループとは•   process.nextTickとは•   node-devでの大論争•   今後どうなる?•   process.nextTickの正しい使    い方おそらく世界初?のNode-v0.8ベースでイベントループを解説(libuvの大幅な変更に追随)(注: 説明はLinuxが対象です。)
Nodeのイベントループとは、• Node の心臓  イベントループが終了したら  Node は死にます。
Nodeのイベントループの正体  Node が起動する時に uv_run() が呼  ばれます。(src/node.cc:2910)https://github.com/joyent/node/blob/v0.8.0-release/deps/uv/src/unix/core.c#L265
イベントループが回り続けるには                              アクティブな handle/req がなけれ                                       ば                                 イベントループが終了https://github.com/joyent/node/blob/v0.8.0-release/deps/uv/src/unix/core.c#L252-261
handle と req の違い• handle  – I/O が発生してない時でもイベントループを    維持  – (例) server.listen()• req  – I/Oが発生している時だけイベントループを    維持  – (例) http.get()
handle と req の種類              handle                       reqASYNC        非同期ジョブの操作      CONNECT       stream接続CHECK        ループの最後の操作      WRITE         stream書き込みFS_EVENT     ファイルイベント操作     SHUTDOWN      stream停止FS_POLL      statの問い合わせ操作   UDP_SEND      udp 送信IDLE         アイドルの時の操作      FS            ファイル操作NAMED_PIPE   名前付きパイプの操作     WORK          ワーカスレッドPOLL         fdイベントの操作      GETADDRINFO   アドレス情報取得PREPARE      ループの最初の操作PROCESS      プロセスの操作TCP          TCPの操作                                      後で見てTIMER        タイマー操作                   おいて下TTYUDP             TTYPの操作             UDPの操作                                       さい。
実際のコードでは、(その1)var http = require('http');         アクティブ                                     ハンドルvar server = http.createServer();      0 アクティブハンドルが無いからNode終了
実際のコードでは、(その2)var http = require('http');var server = http.createServer();                                アクティブserver.listen(1234);           ハンドル追加                               (+1) アクティブハンドルが作成されNode は終了しない。実際は epoll wait (Linux)して
実際のコードでは、(その3)var http = require('http');var server = http.createServer();server.listen(1234, function() {                            アクティブ server.close();          ハンドル削除                             (+1-1=0)});アクティブハンドルがすぐ無効化されるのでNode終了
イベントループの中身  7つのステップ      1. 時刻更新      2. タイマー実行      3. アイドル実行      4. Prepare実行      5. I/Oイベント実行         (libev)      6. Check実行      7. ハンドル終了
Node-v0.8イベントループ概要                             終わり     始まり                                                    setTimeout()nextTick()                            1:時刻更新                7:ハンドル終了         6:run_check                       2:run_timersコールバッ                             イベントループ                 nextTick()  ク                           一周(Tick)                    ユーザ             5:poll                          3:run_idle   プログラム                                   4:run_prepare        libev+kernel       epoll: Linux                                  nextTick()       kqueue: BSD       event port: Solaris                              (注: ユーザプログラムは 3: run_idle から始まる
イベントループを止めてはいけない!                              終わり    始まり                                                    setTimeout() nextTick()                           1:時刻更新                 7:ハンドル終了          6:run_check     2:run_timers                   こんなコードはダメ! while(1) コールバッ   ク                while(1) {                      console.log(‘hoge’);             5:poll }                      3:run_idle                                                  ずっとここ         libev+kernel                             で止まる!                                    4:run_prepare        epoll: Linux        kqueue: BSD                                  nextTick()        event port: Solaris                              (注: ユーザプログラムは 3: run_idle から始まる。
なぜ3カ所も nextTick() があるの?
理由1:呼び出し順番setTimeout(function(){  console.log(‘3:foo’);                                    $ node tick-order.js}, 0);                                    1:piyoprocess.nextTick(function() {                                    2:hoge  console.log(‘2:hoge’);                                    3:foo});console.log(‘1:piyo’);setTimeout() より process.nextTick() が先に呼ばれる                            (注: 将来仕様が変わる可能性があります。)
理由1:呼び出し順番                         終わり     始まり                                                  setTimeout()                                               console.log(‘3:foo’)  nextTick()                      1:時刻更新                 7:ハンドル終了           6:run_check                 2:run_timers                                             console.log(‘1:piyo’)  コールバッ                        イベントループ                    nextTick()    ク                    一周(Tick)               5:poll                    3:run_idle                               4:run_prepare                                               console.log(‘2:hoge’)                                                    nextTick()(注: ユーザプログラムは 3: run_idle から始まる。)
理由2:入れ子の呼び出し順番process.nextTick(function() { setTimeout(function(){    console.log(‘4:foo');                                  $ node tick-order2.js }, 0);                                  1:piyo process.nextTick(function() {                                  2:bar    console.log(‘3:hoge');                                  3:hoge });                                  4:foo console.log(‘2:bar');});console.log(‘1:piyo’);process.nextTick() のスコープ内でも setTimeout()より process.nextTick() が先に呼ばれる                          (注: 将来仕様が変わる可能性があります。)
理由2:入れ子の呼び出し順番                            終わり      始まりconsole.log(‘3:hoge’)                                 setTimeout()                                                   console.log(‘4:foo’)    nextTick()                        1:時刻更新                        7:ハンドル終了             6:run_check                   2:run_timers                                                 console.log(‘1:piyo’)   コールバッ                           イベントループ                     nextTick()     ク                      一周(Tick)                 5:poll                      3:run_idle                                   4:run_prepare                                                   console.log(‘2:bar’)                                                        nextTick()(注: ユーザプログラムは3: run_idleから始まる。)
process.nextTick()の説明(マニュアルより)    イベントループの次以降のループでコールバッ    クを呼び出します。 これは setTimeout(fn, 0) の    単純なエイリアスではなく、 はるかに効率的で    す。for (var i = 0; i < 1024*1024; i++) {       処理時間  process.nextTick(function (){   Math.sqrt(i); } );                   0.360u 0.072s 0:00.44 97.7%}                                            約5倍の差for (var i = 0; i < 1024 * 1024; i++) {  setTimeout(function () {    Math.sqrt(i) }, 0);                 1.700u 0.800s 0:02.51 99.6%}       おそらくリンクリストの生成と時刻取得のオーバヘッドによるものだろう(未
node-v0.9に向けて isaacs からの提案• process.nextTick()でイベントハンドラを追加するのはよくやること  だけど  次のイベントループでハンドラが登録されるまでの間にイベントが  発生したりするとI/Oの取りこぼしが起きてしまう。• 次のイベントが発生する前に確実にハンドラを登録をするために、  V8でJSを実行した直後に process.nextTick() に登録された関数を全部  実行するようにしたい。• 再帰処理とかの展開もそこで行うので次のようなコードでは  setTimeout() は起動しなくなるよ。          setTimeout(function() {           console.log('timeout');          }, 1000);          process.nextTick(function f() {           process.nextTick(f);          });
node-devでの大論争      推進派                  擁護派• 今までの動作がそもそもおか      • 別のAPIにすればいいじゃない  しかった。正しい動作に変え        か  るだけ                • 実際にコード変更するのがど• CPU処理の分散のために再帰を      んなに大変か  使うのは悪いこと、child     • どうせ今さら何言っても聞き  process を使え          入れてくれないだろう• idle用リスナの用途に再帰を使  うのはわからんでもないが、  setTimeoutを使え• API名を変えるのはもう遅い• 実際にI/Oの取りこぼしでバグ  が出ている。この変更でそれ  を直すのが優先する
今後どうなるのか(想像)                                   終わり     始まり                                                          setTimeout()                                            1:時刻更新                      7:ハンドル終了                                                                nextTick()nextTick()                                       2:run_timers    全展開 全展開               6:run_check  コールバッ                                   イベントループ    ク                               一周(Tick)                   5:poll                          3:run_idle                                         4:run_prepare             libev+kernel             epoll: Linux             kqueue: BSD             event port: Solaris                                         再帰は一定回数繰り返したら遅延させるかも
process.nextTickの正しい使い方var events = require('events');var util = require('util');                 非同期イfunction Hoge() {                           ベントの  var self = this;                           生成  process.nextTick(function() {    self.emit('foo');  });}util.inherits(Hoge, events.EventEmitter);var hoge = new Hoge();hoge.on('foo', function() {  console.log('foo event emitted');});
process.nextTickの正しい使い方var events = require('events');var util = require('util');function Hoge(cb) {                         非同期コール  if(cb) {                                  バックの呼び出    process.nextTick(function() {     cb();                                     し    });  }}util.inherits(Hoge, events.EventEmitter);Hoge.prototype.setfoo = function(arg) {  this.foo = arg;};var hoge = new Hoge(function() {  hoge.setfoo('bar');  console.log(hoge.foo);});
process.nextTickの再帰を避けるvar cluster = require('cluster');if (cluster.isMaster) {                  CPU消費処理は  var worker = cluster.fork();            子プロセスで  worker.on('message', function(msg) {    console.log(msg);  });} else {  //子プロセス  while(1) {    process.send(‘hoge’);  }}
まとめ• Node のイベントループの仕組みを良く理解  した上でイベントループを止めないことを意  識してコードを書きましょう。• process.nextTick() は、 – 非同期イベントの発生 – 非同期コールバックの実行 の用途で使いましょう。• CPUを消費する処理には、child process を利  用しましょう。• node-v0.9 では process.nextTick()の動作仕様  が変わる予定です。

Recommended

PPT
Glibc malloc internal
PDF
ソーシャルゲームのためのデータベース設計
PDF
例外設計における大罪
PDF
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
PDF
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
PDF
Where狙いのキー、order by狙いのキー
PPTX
世界一わかりやすいClean Architecture
PDF
CTF for ビギナーズ バイナリ講習資料
PDF
コンテナ未経験新人が学ぶコンテナ技術入門
PDF
こわくない Git
PDF
怖くないSpring Bootのオートコンフィグレーション
PDF
ドメイン駆動設計のためのオブジェクト指向入門
PDF
アーキテクチャから理解するPostgreSQLのレプリケーション
PDF
入門 シェル実装
PDF
SAT/SMTソルバの仕組み
PDF
Dockerからcontainerdへの移行
PPTX
Spanner移行について本気出して考えてみた
PPTX
PostgreSQL開発コミュニティに参加しよう! ~2022年版~(Open Source Conference 2022 Online/Kyoto 発...
PDF
PostgreSQL: XID周回問題に潜む別の問題
PPTX
冬のLock free祭り safe
PPTX
9/14にリリースされたばかりの新LTS版Java 17、ここ3年間のJavaの変化を知ろう!(Open Source Conference 2021 O...
PDF
速習!論理レプリケーション ~基礎から最新動向まで~(PostgreSQL Conference Japan 2022 発表資料)
PDF
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)
PDF
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
PDF
オブジェクト指向できていますか?
PPTX
RustによるGPUプログラミング環境
PDF
ゲーム開発者のための C++11/C++14
PDF
Node-v0.12の新機能について
PDF
Node.jsでブラウザメッセンジャー

More Related Content

PPT
Glibc malloc internal
PDF
ソーシャルゲームのためのデータベース設計
PDF
例外設計における大罪
PDF
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
PDF
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
PDF
Where狙いのキー、order by狙いのキー
PPTX
世界一わかりやすいClean Architecture
PDF
CTF for ビギナーズ バイナリ講習資料
Glibc malloc internal
ソーシャルゲームのためのデータベース設計
例外設計における大罪
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
Where狙いのキー、order by狙いのキー
世界一わかりやすいClean Architecture
CTF for ビギナーズ バイナリ講習資料

What's hot

PDF
コンテナ未経験新人が学ぶコンテナ技術入門
PDF
こわくない Git
PDF
怖くないSpring Bootのオートコンフィグレーション
PDF
ドメイン駆動設計のためのオブジェクト指向入門
PDF
アーキテクチャから理解するPostgreSQLのレプリケーション
PDF
入門 シェル実装
PDF
SAT/SMTソルバの仕組み
PDF
Dockerからcontainerdへの移行
PPTX
Spanner移行について本気出して考えてみた
PPTX
PostgreSQL開発コミュニティに参加しよう! ~2022年版~(Open Source Conference 2022 Online/Kyoto 発...
PDF
PostgreSQL: XID周回問題に潜む別の問題
PPTX
冬のLock free祭り safe
PPTX
9/14にリリースされたばかりの新LTS版Java 17、ここ3年間のJavaの変化を知ろう!(Open Source Conference 2021 O...
PDF
速習!論理レプリケーション ~基礎から最新動向まで~(PostgreSQL Conference Japan 2022 発表資料)
PDF
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)
PDF
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
PDF
オブジェクト指向できていますか?
PPTX
RustによるGPUプログラミング環境
PDF
ゲーム開発者のための C++11/C++14
コンテナ未経験新人が学ぶコンテナ技術入門
こわくない Git
怖くないSpring Bootのオートコンフィグレーション
ドメイン駆動設計のためのオブジェクト指向入門
アーキテクチャから理解するPostgreSQLのレプリケーション
入門 シェル実装
SAT/SMTソルバの仕組み
Dockerからcontainerdへの移行
Spanner移行について本気出して考えてみた
PostgreSQL開発コミュニティに参加しよう! ~2022年版~(Open Source Conference 2022 Online/Kyoto 発...
PostgreSQL: XID周回問題に潜む別の問題
冬のLock free祭り safe
9/14にリリースされたばかりの新LTS版Java 17、ここ3年間のJavaの変化を知ろう!(Open Source Conference 2021 O...
速習!論理レプリケーション ~基礎から最新動向まで~(PostgreSQL Conference Japan 2022 発表資料)
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
オブジェクト指向できていますか?
RustによるGPUプログラミング環境
ゲーム開発者のための C++11/C++14

Similar to そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解する

PDF
Node-v0.12の新機能について
PDF
Node.jsでブラウザメッセンジャー
PDF
Node.js入門
PDF
東京Node学園#3 Domains & Isolates
PDF
Nodejuku01 ohtsu
PPTX
Reactive Programming
PDF
Flow.js
 
PDF
SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...
PDF
PerlとJavaScriptとAndroidとiOSとのんのんバアとオレ
PPTX
イベント駆動プログラミングとI/O多重化
PDF
Node予備校 vol.1 名古屋
PPTX
Node.js - JavaScript Thread Programming
PPTX
React+redux+saga 03
PPTX
たのしいNode.js
PDF
Em synchrony について
PDF
Introduction pp.js
PPTX
EchoyaGinhanazeSu_inoka.pptx
 
PPTX
Reactive
PPTX
オタク×Node.js勉強会
PDF
Janogia20120921 yoshinotakeshi
Node-v0.12の新機能について
Node.jsでブラウザメッセンジャー
Node.js入門
東京Node学園#3 Domains & Isolates
Nodejuku01 ohtsu
Reactive Programming
Flow.js
 
SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...
PerlとJavaScriptとAndroidとiOSとのんのんバアとオレ
イベント駆動プログラミングとI/O多重化
Node予備校 vol.1 名古屋
Node.js - JavaScript Thread Programming
React+redux+saga 03
たのしいNode.js
Em synchrony について
Introduction pp.js
EchoyaGinhanazeSu_inoka.pptx
 
Reactive
オタク×Node.js勉強会
Janogia20120921 yoshinotakeshi

More from shigeki_ohtsu

PDF
Node最新トピックス
PDF
TLS, HTTP/2演習
PDF
HTTP/2, QUIC入門
PDF
SSL/TLSの基礎と最新動向
PDF
HTTP/2の現状とこれから
PDF
Node-v0.12のTLSを256倍使いこなす方法
PDF
Technical Overview of QUIC
PDF
httpbis interim@チューリッヒ レポート
PDF
第43回HTML5とか勉強会 SPDY/QUICデモ
PDF
HTTP/2.0がもたらす Webサービスの進化(後半)
PDF
HTTP/2.0 HPAC-03 エンコーディング手法 by tatsuhiro_t
PDF
httpbis interim@シアトル レポート (第2回HTTP/2.0接続試験)
PDF
Node の HTTP/2.0 モジュール iij-http2 の実装苦労話
PPTX
httpbis interim とhttp2.0相互接続試験の話
PPTX
Stream2の基本
PDF
Node.js で SPDYのベンチマーク体験サイトを作りました
PPTX
SPDYの話
PPTX
SPDYの中身を見てみよう
PPTX
node-gypを使ったネイティブモジュールの作成
Node最新トピックス
TLS, HTTP/2演習
HTTP/2, QUIC入門
SSL/TLSの基礎と最新動向
HTTP/2の現状とこれから
Node-v0.12のTLSを256倍使いこなす方法
Technical Overview of QUIC
httpbis interim@チューリッヒ レポート
第43回HTML5とか勉強会 SPDY/QUICデモ
HTTP/2.0がもたらす Webサービスの進化(後半)
HTTP/2.0 HPAC-03 エンコーディング手法 by tatsuhiro_t
httpbis interim@シアトル レポート (第2回HTTP/2.0接続試験)
Node の HTTP/2.0 モジュール iij-http2 の実装苦労話
httpbis interim とhttp2.0相互接続試験の話
Stream2の基本
Node.js で SPDYのベンチマーク体験サイトを作りました
SPDYの話
SPDYの中身を見てみよう
node-gypを使ったネイティブモジュールの作成

そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解する

  • 1.
    そうだったのか! よくわかる process.nextTick() Node.jsのイベントループを理解する IIJ 大津 繁樹 (@jovi0608) 2012年6月28日 東京Node学園6時限目
  • 3.
    Nodeの歩み(参考)2007/10 libev公開 2010/08 nodejs_jp開始2008/05 libeio公開 2010/09 no.de開始2009/09 Google V8公開 2010/11 Joyent管轄へ2009/02 ry Node開発開始 2011/02 node-v0.4.0リリース2009/05 node-v0.0.1リリース 2011/03 東京Node学園#12009/06 nodejs ML開始 2011/10 東京Node学園祭2009/10 npm公開 2011/11 node-v0.6.0リリース2009/11 JSConf EU ry発表 2011/12 Azureサポート2010/04 Herokuサポート 2012/01 isaacs管理へ2010/08 node-v0.2.0リリース 2012/06 node-v0.8.0リリース
  • 4.
    今日の話•Nodeのイベントループとは• process.nextTickとは• node-devでの大論争• 今後どうなる?• process.nextTickの正しい使 い方おそらく世界初?のNode-v0.8ベースでイベントループを解説(libuvの大幅な変更に追随)(注: 説明はLinuxが対象です。)
  • 5.
    Nodeのイベントループとは、• Node の心臓 イベントループが終了したら Node は死にます。
  • 6.
    Nodeのイベントループの正体 Nodeが起動する時に uv_run() が呼 ばれます。(src/node.cc:2910)https://github.com/joyent/node/blob/v0.8.0-release/deps/uv/src/unix/core.c#L265
  • 7.
    イベントループが回り続けるには アクティブな handle/req がなけれ ば イベントループが終了https://github.com/joyent/node/blob/v0.8.0-release/deps/uv/src/unix/core.c#L252-261
  • 8.
    handle と reqの違い• handle – I/O が発生してない時でもイベントループを 維持 – (例) server.listen()• req – I/Oが発生している時だけイベントループを 維持 – (例) http.get()
  • 9.
    handle と reqの種類 handle reqASYNC 非同期ジョブの操作 CONNECT stream接続CHECK ループの最後の操作 WRITE stream書き込みFS_EVENT ファイルイベント操作 SHUTDOWN stream停止FS_POLL statの問い合わせ操作 UDP_SEND udp 送信IDLE アイドルの時の操作 FS ファイル操作NAMED_PIPE 名前付きパイプの操作 WORK ワーカスレッドPOLL fdイベントの操作 GETADDRINFO アドレス情報取得PREPARE ループの最初の操作PROCESS プロセスの操作TCP TCPの操作 後で見てTIMER タイマー操作 おいて下TTYUDP TTYPの操作 UDPの操作 さい。
  • 10.
    実際のコードでは、(その1)var http =require('http'); アクティブ ハンドルvar server = http.createServer(); 0 アクティブハンドルが無いからNode終了
  • 11.
    実際のコードでは、(その2)var http =require('http');var server = http.createServer(); アクティブserver.listen(1234); ハンドル追加 (+1) アクティブハンドルが作成されNode は終了しない。実際は epoll wait (Linux)して
  • 12.
    実際のコードでは、(その3)var http =require('http');var server = http.createServer();server.listen(1234, function() { アクティブ server.close(); ハンドル削除 (+1-1=0)});アクティブハンドルがすぐ無効化されるのでNode終了
  • 13.
    イベントループの中身 7つのステップ 1. 時刻更新 2. タイマー実行 3. アイドル実行 4. Prepare実行 5. I/Oイベント実行 (libev) 6. Check実行 7. ハンドル終了
  • 14.
    Node-v0.8イベントループ概要 終わり 始まり setTimeout()nextTick() 1:時刻更新 7:ハンドル終了 6:run_check 2:run_timersコールバッ イベントループ nextTick() ク 一周(Tick) ユーザ 5:poll 3:run_idle プログラム 4:run_prepare libev+kernel epoll: Linux nextTick() kqueue: BSD event port: Solaris (注: ユーザプログラムは 3: run_idle から始まる
  • 15.
    イベントループを止めてはいけない! 終わり 始まり setTimeout() nextTick() 1:時刻更新 7:ハンドル終了 6:run_check 2:run_timers こんなコードはダメ! while(1) コールバッ ク while(1) { console.log(‘hoge’); 5:poll } 3:run_idle ずっとここ libev+kernel で止まる! 4:run_prepare epoll: Linux kqueue: BSD nextTick() event port: Solaris (注: ユーザプログラムは 3: run_idle から始まる。
  • 16.
  • 17.
    理由1:呼び出し順番setTimeout(function(){ console.log(‘3:foo’); $ node tick-order.js}, 0); 1:piyoprocess.nextTick(function() { 2:hoge console.log(‘2:hoge’); 3:foo});console.log(‘1:piyo’);setTimeout() より process.nextTick() が先に呼ばれる (注: 将来仕様が変わる可能性があります。)
  • 18.
    理由1:呼び出し順番 終わり 始まり setTimeout() console.log(‘3:foo’) nextTick() 1:時刻更新 7:ハンドル終了 6:run_check 2:run_timers console.log(‘1:piyo’) コールバッ イベントループ nextTick() ク 一周(Tick) 5:poll 3:run_idle 4:run_prepare console.log(‘2:hoge’) nextTick()(注: ユーザプログラムは 3: run_idle から始まる。)
  • 19.
    理由2:入れ子の呼び出し順番process.nextTick(function() { setTimeout(function(){ console.log(‘4:foo'); $ node tick-order2.js }, 0); 1:piyo process.nextTick(function() { 2:bar console.log(‘3:hoge'); 3:hoge }); 4:foo console.log(‘2:bar');});console.log(‘1:piyo’);process.nextTick() のスコープ内でも setTimeout()より process.nextTick() が先に呼ばれる (注: 将来仕様が変わる可能性があります。)
  • 20.
    理由2:入れ子の呼び出し順番 終わり 始まりconsole.log(‘3:hoge’) setTimeout() console.log(‘4:foo’) nextTick() 1:時刻更新 7:ハンドル終了 6:run_check 2:run_timers console.log(‘1:piyo’) コールバッ イベントループ nextTick() ク 一周(Tick) 5:poll 3:run_idle 4:run_prepare console.log(‘2:bar’) nextTick()(注: ユーザプログラムは3: run_idleから始まる。)
  • 21.
    process.nextTick()の説明(マニュアルより) イベントループの次以降のループでコールバッ クを呼び出します。 これは setTimeout(fn, 0) の 単純なエイリアスではなく、 はるかに効率的で す。for (var i = 0; i < 1024*1024; i++) { 処理時間 process.nextTick(function (){ Math.sqrt(i); } ); 0.360u 0.072s 0:00.44 97.7%} 約5倍の差for (var i = 0; i < 1024 * 1024; i++) { setTimeout(function () { Math.sqrt(i) }, 0); 1.700u 0.800s 0:02.51 99.6%} おそらくリンクリストの生成と時刻取得のオーバヘッドによるものだろう(未
  • 22.
    node-v0.9に向けて isaacs からの提案•process.nextTick()でイベントハンドラを追加するのはよくやること だけど 次のイベントループでハンドラが登録されるまでの間にイベントが 発生したりするとI/Oの取りこぼしが起きてしまう。• 次のイベントが発生する前に確実にハンドラを登録をするために、 V8でJSを実行した直後に process.nextTick() に登録された関数を全部 実行するようにしたい。• 再帰処理とかの展開もそこで行うので次のようなコードでは setTimeout() は起動しなくなるよ。 setTimeout(function() { console.log('timeout'); }, 1000); process.nextTick(function f() { process.nextTick(f); });
  • 23.
    node-devでの大論争 推進派 擁護派• 今までの動作がそもそもおか • 別のAPIにすればいいじゃない しかった。正しい動作に変え か るだけ • 実際にコード変更するのがど• CPU処理の分散のために再帰を んなに大変か 使うのは悪いこと、child • どうせ今さら何言っても聞き process を使え 入れてくれないだろう• idle用リスナの用途に再帰を使 うのはわからんでもないが、 setTimeoutを使え• API名を変えるのはもう遅い• 実際にI/Oの取りこぼしでバグ が出ている。この変更でそれ を直すのが優先する
  • 24.
    今後どうなるのか(想像) 終わり 始まり setTimeout() 1:時刻更新 7:ハンドル終了 nextTick()nextTick() 2:run_timers 全展開 全展開 6:run_check コールバッ イベントループ ク 一周(Tick) 5:poll 3:run_idle 4:run_prepare libev+kernel epoll: Linux kqueue: BSD event port: Solaris 再帰は一定回数繰り返したら遅延させるかも
  • 25.
    process.nextTickの正しい使い方var events =require('events');var util = require('util'); 非同期イfunction Hoge() { ベントの var self = this; 生成 process.nextTick(function() { self.emit('foo'); });}util.inherits(Hoge, events.EventEmitter);var hoge = new Hoge();hoge.on('foo', function() { console.log('foo event emitted');});
  • 26.
    process.nextTickの正しい使い方var events =require('events');var util = require('util');function Hoge(cb) { 非同期コール if(cb) { バックの呼び出 process.nextTick(function() { cb(); し }); }}util.inherits(Hoge, events.EventEmitter);Hoge.prototype.setfoo = function(arg) { this.foo = arg;};var hoge = new Hoge(function() { hoge.setfoo('bar'); console.log(hoge.foo);});
  • 27.
    process.nextTickの再帰を避けるvar cluster =require('cluster');if (cluster.isMaster) { CPU消費処理は var worker = cluster.fork(); 子プロセスで worker.on('message', function(msg) { console.log(msg); });} else { //子プロセス while(1) { process.send(‘hoge’); }}
  • 28.
    まとめ• Node のイベントループの仕組みを良く理解 した上でイベントループを止めないことを意 識してコードを書きましょう。• process.nextTick() は、 – 非同期イベントの発生 – 非同期コールバックの実行 の用途で使いましょう。• CPUを消費する処理には、child process を利 用しましょう。• node-v0.9 では process.nextTick()の動作仕様 が変わる予定です。

[8]ページ先頭

©2009-2025 Movatter.jp