Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Node-v0.12の新機能について
IIJ 大津 繁樹
2014年4月24日
東京Node学園12時限目
ちょっと早く
フライイングで紹介
盛りだくさんよ。
どこまで話せるかな?
自己紹介
• 株式会社 インターネットイニシアティブ(IIJ)
プロダクト本部アプリケーション開発部所属
• twitter: @jovi0608
• github: http://github.com/shigeki
• ブログ: 「ぼちぼち...
本日の内容(*)
1. Node-v0.12の概要
2. ES6 /7対応 (Promise, Object.observe, WeakMap/WeakSet)
3. Streams3 (Stream1+2の復習も兼ねて)
4. 同期child...
Nodeのこれまでの歩み
2007/10 libev公開
2008/05 libeio公開
2008/09 Google V8公開
2009/02 ryan dahl Node開発開始
2009/05 node-v0.0.1 リリース
2009...
Node-v0.12概要
• Node-v0.12は、Node-v1.0の Release Candidate
の位置付け。 まだリリースされていません!
• Node-v0.10から安定性と性能向上を中心に、派
手な新機能の追加や大幅なAPI...
Node の ES6/ES7対応
• Chrome M35 が何かと機能がてんこ盛り。
• そこに載っているV8 3.25 で ES6/ES7 の一部機能
が先行的に default で有効に(*)
• Node も V8 3.25 にアップデ...
NodeのES6系ブログエントリー
詳しくは、こっち読んで下さい。
1. Node.jsにPromiseが再びやって来た!
– http://d.hatena.ne.jp/jovi0608/20140319/1395199285
2. Obje...
Promise
• Promise A+仕様をベースにES6で採用
• 非同期処理(成功時:OnFulfill, エラー時:
OnRejected)を登録、実行
• then()やcatch()でメソッドチェーンの利用
• then() を持っ...
Promies利用例
引数で指定したファイルの確認を Promise で処理するサンプル
var fs = require('fs');
var file = process.argv[2] || __filename;
var promise...
Promiseの利用例
こんなコールバック地獄が
fs.readdir(dir1, function(...) { // dir1中のファイルリストを 取得
fs.readFile(file1, function(...) { // その中のf...
Promiseの利用例
こんな風に変えられます
function compareDirHash(dir1, dir2) {
return compareFilesPromise(dir1, dir2).then(function(files) ...
Object.observe
Array.observe
• オブジェクトのプロパティや配列要素の変更を検
知してコールバックを呼び出すことができる機能
• 通常JS実行の最後にコールバックが呼び出される
が、 同期的に扱うことも可能
(Obj...
Object.observe 実行例
検知できるイベント(*)
Object.observe Array.observe
add add
update update
delete delete
setPrototype splice
recon...
1:時刻更新
5:poll
始まり
終わり
4:run_prepare
setTimeout()
setInterval()
I/Oコールバック
3:run_idle
Node-v0.12
イベントループ
一周(Tick)
kernel I/O...
WeakMap/WeakSet
• オブジェクトのみをキーにしたハッシュテーブル。
• WeakMapは、キーと値を WeakSet はキーのみ登録
• 弱参照なのでキーがGCされるとエントリーが自動的
に削除される。
• for とかで内部の...
WeakMap利用例 (*)
WeakMapを使った Private変数の隠匿
var weakmap = new WeakMap();
module.exports = Hoge;
function Hoge(size) {
size = +...
Node.js v0.10 Stream2 のきほん
補習資料
http://www.slideshare.net/shigeki_ohtsu/stream2-kihon
せっかくの入学式だから復習を
Stream は大事なクラス
events.EventEmitter
stream.Stream
node-v0.10
stream.Readable stream.Writable
http.outgoingMessagestream.Dup...
Stream1 おさらい
Readable
Stream
src
データの流れ
dataイベントから
データの読み込み
pause() による読み
込み停止
resume() による読
み込み再開
補習資料
Stream1 の問題
var server = http.createServer(function(req, res) {
setTimeout(function() {
var data = '';
req.on('data', func...
Stream1 の問題
リスナ
Readable
Stream
データ
Readable Stream が 'data' イベントを生成し
た時にリスナが存在しなければ、 データは失
われることに注意してください
補習資料
Stream1 の問題
pause()→drain→resume()→pause()
閉め→開け→閉め→開け
開け→閉め→開け→閉め
不安定な流れに弱い
drain
drain
補習資料
Stream2とは?
内部タンク付きストリーム
ストリーム内部にデータバッファを持つことによって、
• データの取りこぼしをなくす
• 不安定な流れに影響されにくくする
• ただし上限値(highWaterMark: default 16kB)...
ReadableStream のプレイヤー
ソース 実装者 消費者
データの源
ストリーム本体。
ソースからデータ
を読み込み内部
バッファに蓄える
ストリームから
データを受け取り
利用する人
push() read()
_read()
re...
Stream2の問題点
• readable(pull型データ取得)と data(push型デー
タ取得)の両方使いたい
• 一度 old-mode (Stream1互換)に行ったら戻れ
ない
• httpモジュール内で もdata イベント使...
Streams3
Readable Streamの変更
• APIを変えない。挙動を変更。
• old mode(Stream1互換) と new mode
(Stream2) の区別をなくす。
• flowing/non-flowingモード...
Stream2と3の違い
new mode
pipe()
readable
イベント
old mode
dataイベント
resume()
pause()
non-flowing
mode(初期)
flowing
mode
一度行ったら
戻れな...
Streams3 モードの行き来(その1)
paused → flowing → paused (pauseの利用)
var rstream = require('fs').createReadStream(__filename);
rstre...
Streams3 モードの行き来(その2)
paused → flowing (resumeの利用)
var rstream = require('fs').createReadStream(__filename);
rstream.resum...
Streams3 モードの行き来(その3)
paused → flowing (pipeの利用)
var rstream = require('fs').createReadStream(__filename);
rstream.on('rea...
Streams3 モードの行き来(その4)
paused → flowing → pause (dataイベント削除+unpipeの利用)
var rstream = require('fs').createReadStream(__filen...
その他 Stream の変更
Writable Stream のAPI拡張
• writable.cork() 書き込みを停止して溜める
• writable.uncork() 溜めるのやめる
• writable._writev(chunks...
同期child_process
• 最近利用が普及してきたフロントエンド用タスク
処理向けに、同期で子プロセス処理をしたい
ニーズに対応
• spawnSync, execFileSync, execSyncの三種類
• 返り値は、spawnS...
execSync使用例
Node Shell
var execSync = require('child_process').execSync;
var readline = require('readline');
var rl = read...
beforeExitイベント新設
• process の exit オブジェクトは、JavaScriptの実
行はできるけど、イベントループが終了してい
るため、もうI/O処理はできない状態。
• プロセス終了間際に、ゴミ掃除やログの送信、
他...
beforeExit サンプル
httpクライアントの一時ファイル掃除
var fs = require(‘fs’), http = require('http');
var tmpdir = './tmpdir/', hosts = ['lo...
新vmモジュール
• vmモジュールとは、JavaScriptを実行するモジュール。
• Context やsandboxを指定でき、iframe 上のJavaScript実行
のようなもの(でもセキュリティ的に完全分離してない)。
• 信頼で...
旧vmモジュールのダメな例
var vm = require('vm');
var sandbox = Object.create({foo: 'hoge'});
var ret = vm.runInNewContext('foo;', san...
新vmモジュール
• node_contextfy モジュールをベースにコアに
取り込み。
• 完全に V8::Context を分離。
• 先の不具合を解消。
• WatchDogを導入、timeout 指定も可能に。
var vm = re...
tracing モジュール
V8のGCイベントとHeap統計情報を取得できます。
その他 AsyncListener:
AsyncWrapクラスに引っ掛けてオブジェクト生成、コールバック
起動前後でリスナを起動させるもの。もともとDomainの...
Cluster RoundRobin
• 従来のClusterは、複数のプロセスが同時に
accept(2) してkernelが割り当てを決定。
• kernel側がコンテキストをなるべく変更しないよう
最適化→処理するプロセスが偏る問題
• ...
Cluster Modeの比較・検証する
var cluster = require('cluster'), http = require('http');
if (process.argv[2] === 'none') cluster.sch...
結果
ab -n 1000 http://localhost:8080/
cluster.SCHED_NONE
$ node test.js none
cluster.schedulingPolicy: None
Listening on pi...
その他高速化ネタ
• http.ClientRequestの同時接続制限を廃止
• Buffer実装をslaballocator廃止、smalloc化でV8管
理に変更、高速化を達成
• TLS性能の高速化
– Paypalベンチでは2倍程度(...
Any Questions?
(special thanks いらすとや http://www.irasutoya.com/ )
Upcoming SlideShare
Loading in …5
×

Node-v0.12の新機能について

22,834 views

Published on

Published in: Internet
  • Be the first to comment

Node-v0.12の新機能について

  1. 1. Node-v0.12の新機能について IIJ 大津 繁樹 2014年4月24日 東京Node学園12時限目 ちょっと早く フライイングで紹介 盛りだくさんよ。 どこまで話せるかな?
  2. 2. 自己紹介 • 株式会社 インターネットイニシアティブ(IIJ) プロダクト本部アプリケーション開発部所属 • twitter: @jovi0608 • github: http://github.com/shigeki • ブログ: 「ぼちぼち日記」 http://d.hatena.ne.jp/jovi0608/ • NodeやHTTP/2など新しいもの好き
  3. 3. 本日の内容(*) 1. Node-v0.12の概要 2. ES6 /7対応 (Promise, Object.observe, WeakMap/WeakSet) 3. Streams3 (Stream1+2の復習も兼ねて) 4. 同期child_process, beforeExitイベント(process) 5. 新 vm モジュール (時間があれば) 6. tracing モジュール (時間があれば) 7. Clusterのラウンドロビンモード(時間があれば) 8. 高速化の話(時間があれば) 全体的な性能向上も大きな売り。ベンチ結果は、おそらく リリース時に公式な数値が出るので今回は出しません。 (* 2014/04/23時点での master branch が対象)
  4. 4. Nodeのこれまでの歩み 2007/10 libev公開 2008/05 libeio公開 2008/09 Google V8公開 2009/02 ryan dahl Node開発開始 2009/05 node-v0.0.1 リリース 2009/06 nodejs ML開始 2009/10 npm公開 2009/11 JSConf EU ry発表 2010/04 Herokuサポート 2010/08 node-v0.2 リリース 2010/11 Joyent管轄へ 2011/02 node-v0.4 リリース 2011/03 libuv 開発開始 2011/11 node-v0.6 リリース 2011/12 Windows Azureサポート 2012/01 管理者が isaacsに変更 2012/06 node-v0.8 リリース 2013/03 node-v0.10 リリース 2014/01 管理者が TJ Fontaineに変更 ? node-v0.12 リリース
  5. 5. Node-v0.12概要 • Node-v0.12は、Node-v1.0の Release Candidate の位置付け。 まだリリースされていません! • Node-v0.10から安定性と性能向上を中心に、派 手な新機能の追加や大幅なAPI廃止・変更はあ りません(ただし仕様や挙動変更の部分は多々あります)。 • コアの中身は大幅に変更されてます。 • V8も大きくバージョンアップ 3.14→3.25 。それに 伴い V8 APIが大幅に変更→以前のNativeモ ジュールは大きく書き換えが必要。 • libuv もいろいろ細かく変わっていますが、0.10ほ どではないので…
  6. 6. Node の ES6/ES7対応 • Chrome M35 が何かと機能がてんこ盛り。 • そこに載っているV8 3.25 で ES6/ES7 の一部機能 が先行的に default で有効に(*) • Node も V8 3.25 にアップデート • Promise/Object.observe/WeakMap/WeakSet が harmony オプションなしで利用が可能になった。 • 全部詳細説明すると時間が足りないので簡単に。 (* なぜかV8 3.26では要オプションに戻されてます)
  7. 7. NodeのES6系ブログエントリー 詳しくは、こっち読んで下さい。 1. Node.jsにPromiseが再びやって来た! – http://d.hatena.ne.jp/jovi0608/20140319/1395199285 2. Object.observe()とNode.jsのイベントループの関係 – http://d.hatena.ne.jp/jovi0608/20140320/1395294325 3. Node-v0.12からデフォルトでES6の一部が使えるようになった (WeakMap解説編) – http://d.hatena.ne.jp/jovi0608/20140418/1397789018
  8. 8. Promise • Promise A+仕様をベースにES6で採用 • 非同期処理(成功時:OnFulfill, エラー時: OnRejected)を登録、実行 • then()やcatch()でメソッドチェーンの利用 • then() を持ったオブジェクト(thenable)からプ ロミスオブジェクトを生成 • Promise.all([p1, p2, …]) で全てのプロミスオブ ジェクトの成功を一括処理
  9. 9. Promies利用例 引数で指定したファイルの確認を Promise で処理するサンプル var fs = require('fs'); var file = process.argv[2] || __filename; var promise = new Promise(function(onFulfilled, onRejected) { fs.stat(file, function(err, stat) { // return stat object when fulfilled err ? onRejected(err) : onFulfilled(stat); }); }); // 正常処理なら onFulfilled, エラーなら onRejected が実行される promise.then( function(stat) { console.log('Fulfilled:', file, stat); }, function(error) { console.log("Rejected:", error.message); } );
  10. 10. Promiseの利用例 こんなコールバック地獄が fs.readdir(dir1, function(...) { // dir1中のファイルリストを 取得 fs.readFile(file1, function(...) { // その中のfile1を 読み込み hash.update(data); // ファイルデータのハッシュ値を計算 fs.readdir(dir2, function(...) { // dir2中のファイルリストを 取得 fs.readFile(file2, function(...) { ... }); }); }); }); dir1 と dir2 のディレクトリ中のファイルハッシュの比較
  11. 11. Promiseの利用例 こんな風に変えられます function compareDirHash(dir1, dir2) { return compareFilesPromise(dir1, dir2).then(function(files) { return Promise.all(files.map(function(file) { return compareHashPromise(dir1, dir2, file); })); }).then( function(x) { // 正常処理 }, function(err) { // all case of errors // エラー処理 } ); } compareDirHash('./dir1/', './dir2/'); dir1 と dir2 のディレクトリ中のファイルハッシュの比較 Array.mapで処理結果を 配列にしてから Promise.all() を使うと便利 全部正常に 完了した時の 処理がまとめ て書ける エラー処理も 扱いやすい
  12. 12. Object.observe Array.observe • オブジェクトのプロパティや配列要素の変更を検 知してコールバックを呼び出すことができる機能 • 通常JS実行の最後にコールバックが呼び出される が、 同期的に扱うことも可能 (Object.deliverChangeRecords ) • Notifyオブジェクトを使って独自のイベントの追加、 呼び出しも可能 • Angular.JS2.0のデータバインディングで利用予定 (* ES7の機能です)
  13. 13. Object.observe 実行例 検知できるイベント(*) Object.observe Array.observe add add update update delete delete setPrototype splice reconfigure preventExtension var obj = {}; function callback(changeRecord) { console.log(changeRecord); } Object.observe(obj, callback); obj.a = 1; // プロパティ追加 $ node test.js [ { type: 'add', object: { a: 1 }, name: 'a' } ] 実行例 (* Notifierを使えば独自イベントも追加可能)
  14. 14. 1:時刻更新 5:poll 始まり 終わり 4:run_prepare setTimeout() setInterval() I/Oコールバック 3:run_idle Node-v0.12 イベントループ 一周(Tick) kernel I/O epoll: Linux kqueue: MacOS/BSD event port: Solaris IOCP: Windows 2:run_timers6:run_check setImmeidate() メインモジュールの 読み込み・実行 process.nextTick() 再帰展開・実行 Object.observe() Callback実行 0: Load (* コールバック中に Object.observeがあればJS実 行の最後に起動されます。)
  15. 15. WeakMap/WeakSet • オブジェクトのみをキーにしたハッシュテーブル。 • WeakMapは、キーと値を WeakSet はキーのみ登録 • 弱参照なのでキーがGCされるとエントリーが自動的 に削除される。 • for とかで内部のエントリーを列挙したり、格納されて いるエントリー数を取得するようなことはできない。 • soft field と object cache という目的で仕様化された • ブラウザでは、DOMのプロパティを勝手に拡張して フィールドを付け加えるのではなく、WeakMapを使う。 • (何故か?) IE11 で WeakMap が実装済
  16. 16. WeakMap利用例 (*) WeakMapを使った Private変数の隠匿 var weakmap = new WeakMap(); module.exports = Hoge; function Hoge(size) { size = +size || 8; var rand = require('crypto').randomBytes(size); // thisをキーとしてプライベート変数をWeakMapに格納 weakmap.set(this, rand); }; Hoge.prototype.getRand = function() { // WeakMapからプライベート変数を取り出す return weakmap.get(this); }; (* 別にNode固有の使い方じゃありません) インスタンス がGCされれば 勝手になくな るよ
  17. 17. Node.js v0.10 Stream2 のきほん 補習資料 http://www.slideshare.net/shigeki_ohtsu/stream2-kihon せっかくの入学式だから復習を
  18. 18. Stream は大事なクラス events.EventEmitter stream.Stream node-v0.10 stream.Readable stream.Writable http.outgoingMessagestream.Duplex stream.Transform net.Socket tls.CleartextStream その他crypto系クラス crypto sign/verify http.IncomingMessage 補習資料
  19. 19. Stream1 おさらい Readable Stream src データの流れ dataイベントから データの読み込み pause() による読み 込み停止 resume() による読 み込み再開 補習資料
  20. 20. Stream1 の問題 var server = http.createServer(function(req, res) { setTimeout(function() { var data = ''; req.on('data', function(chunk) { data += chunk; }); req.on('end', function() { console.log(data); }); res.writeHead(200); res.end(); }, 1000); }).listen(8080); POSTデータをちゃんと取れる? 補習資料
  21. 21. Stream1 の問題 リスナ Readable Stream データ Readable Stream が 'data' イベントを生成し た時にリスナが存在しなければ、 データは失 われることに注意してください 補習資料
  22. 22. Stream1 の問題 pause()→drain→resume()→pause() 閉め→開け→閉め→開け 開け→閉め→開け→閉め 不安定な流れに弱い drain drain 補習資料
  23. 23. Stream2とは? 内部タンク付きストリーム ストリーム内部にデータバッファを持つことによって、 • データの取りこぼしをなくす • 不安定な流れに影響されにくくする • ただし上限値(highWaterMark: default 16kB)が決まっている • オブジェクト一つをストリームバッファとして扱える objectMode をサポート • old mode(Stream1互換)に変更可 補習資料
  24. 24. ReadableStream のプレイヤー ソース 実装者 消費者 データの源 ストリーム本体。 ソースからデータ を読み込み内部 バッファに蓄える ストリームから データを受け取り 利用する人 push() read() _read() readable 補習資料
  25. 25. Stream2の問題点 • readable(pull型データ取得)と data(push型デー タ取得)の両方使いたい • 一度 old-mode (Stream1互換)に行ったら戻れ ない • httpモジュール内で もdata イベント使いたい 参考:http://www.joyent.com/blog/streams-in-node socketがせっかく Stream2 なのに データ取り出しが ondata関数呼び 出しで、オーバヘッドになってる。 こうしたい
  26. 26. Streams3 Readable Streamの変更 • APIを変えない。挙動を変更。 • old mode(Stream1互換) と new mode (Stream2) の区別をなくす。 • flowing/non-flowingモードを flowing/paused モードにして、どちらも行き来OK • readable イベント時に data イベントも一緒に 出す。
  27. 27. Stream2と3の違い new mode pipe() readable イベント old mode dataイベント resume() pause() non-flowing mode(初期) flowing mode 一度行ったら 戻れない pipe(),data イベント,resume() paused mode(初期) flowing mode readable イベント, pause() 相互に行き来OK Streams2 Streams3 dataイベントも 一緒に出す Stream1と2のmix
  28. 28. Streams3 モードの行き来(その1) paused → flowing → paused (pauseの利用) var rstream = require('fs').createReadStream(__filename); rstream.on('readable', function() { while((b = rstream.read(1)) !== null) { console.log('read:', b.toString()); } }); var bytesRead = 0; rstream.on(‘data’, function(chunk) { // flowing mode へ bytesRead += chunk.length; console.log(bytesRead + ' bytes read'); }); rstream.pause(); // paused modeへ 読み込み進捗率を表示 1バイトずつ表示 readableイベントと dataイベントの両立が可能になった
  29. 29. Streams3 モードの行き来(その2) paused → flowing (resumeの利用) var rstream = require('fs').createReadStream(__filename); rstream.resume(); // flowing mode へ // data listener がないのでデータが失われてるよ! rstream.on('readable', function() { console.log(rstream.read()); // 出力なし }); rstream.on('end', function() { console.log('stream end'); }); flowing mode では readできな いよ 内部バッファを消 費しないと end は発火しない
  30. 30. Streams3 モードの行き来(その3) paused → flowing (pipeの利用) var rstream = require('fs').createReadStream(__filename); rstream.on('readable', function() { var b; while((b = rstream.read(1)) !== null) { console.log('read:', b.toString()); } }); rstream.pipe(process.stdout); // flowing mode へ その1の pipe版
  31. 31. Streams3 モードの行き来(その4) paused → flowing → pause (dataイベント削除+unpipeの利用) var rstream = require('fs').createReadStream(__filename); rstream.on('readable', function() { var b; while((b = rstream.read(1)) !== null) { console.log('read:', b.toString()); } }); rstream.pipe(process.stdout); // flowing mode へ rstream.removeAllListeners(‘data’).unpipe(); // paused modeへ dataイベントを全て除いて pipe も外 したらやっと paused modeに変遷
  32. 32. その他 Stream の変更 Writable Stream のAPI拡張 • writable.cork() 書き込みを停止して溜める • writable.uncork() 溜めるのやめる • writable._writev(chunks, callback) 一気に書き 出す
  33. 33. 同期child_process • 最近利用が普及してきたフロントエンド用タスク 処理向けに、同期で子プロセス処理をしたい ニーズに対応 • spawnSync, execFileSync, execSyncの三種類 • 返り値は、spawnSyncがオブジェクト、他は stdout のBuffer • 子プロセス処理中は、親プロセスはブロッキング 状態(正確には別のイベントループを生成し、SIGCHLDを待つ) • エラー発生やタイムアウト時はThrowされるので 注意
  34. 34. execSync使用例 Node Shell var execSync = require('child_process').execSync; var readline = require('readline'); var rl = readline.createInterface(process.stdin, process.stdout); rl.setPrompt('Node_Shell$ '); rl.prompt(); rl.on('line', function(cmd) { try { var ret = execSync(cmd.trim()); // 同期処理 console.log(ret + ''); } catch(e) { console.err(e.code); } rl.prompt(); });
  35. 35. beforeExitイベント新設 • process の exit オブジェクトは、JavaScriptの実 行はできるけど、イベントループが終了してい るため、もうI/O処理はできない状態。 • プロセス終了間際に、ゴミ掃除やログの送信、 他へのhookなどI/O処理をしたい。 • プロセス終了直前に、もう一度イベントループ を回してJavaScript実行できる beforeExit イベ ントを process オブジェクトに新設。
  36. 36. beforeExit サンプル httpクライアントの一時ファイル掃除 var fs = require(‘fs’), http = require('http'); var tmpdir = './tmpdir/', hosts = ['localhost']; if (!fs.existsSync(tmpdir)) fs.mkdirSync(tmpdir); hosts.forEach(function(host) { http.get({hostname: host}).on('response', function(res) { var tmpf = tmpdir + host; res.pipe(fs.createWriteStream(tmpf)).on('finish', function() { console.log('Do something special to the tmp file.'); }); }); }); // Cleanup temporary files process.once('beforeExit', function() { fs.readdir(tmpdir, function(err, files) { files.forEach(function(file) { fs.unlink(tmpdir + file); }); }); }); プロセスが終了する前に一時ファイルを 全部削除する。 リスナ登録を once にしておかないと、再 帰で呼び出されるから注意です。 httpクライアントによる コンテンツの取得と一 時ファイルへの書き込 み全部終わったら、イ ベントループが終了。 出ていく前に 掃除しろよー
  37. 37. 新vmモジュール • vmモジュールとは、JavaScriptを実行するモジュール。 • Context やsandboxを指定でき、iframe 上のJavaScript実行 のようなもの(でもセキュリティ的に完全分離してない)。 • 信頼できない外部のJSを実行・評価するような時に使う。(使 用例:UglifyJS2とか) • Node-v0.10までは色々問題があった。 Node-v0.10.26 vmモジュールマニュアルより vm に渡された sandbox オブジェクトを global に単純に clone し てたため次頁のような issue が残っていた。
  38. 38. 旧vmモジュールのダメな例 var vm = require('vm'); var sandbox = Object.create({foo: 'hoge'}); var ret = vm.runInNewContext('foo;', sandbox); console.log(ret); // Reference Error var vm = require('vm'); var sandbox = {foo: 'hoge'}; var ret = vm.runInNewContext('this;', sandbox); console.log(ret); // {} が返る var vm = require('vm'); var code = "setTimeout(function(){foo = 1}, 2000);"; var sandbox = {foo: 'hoge', setTimeout: setTimeout}; var ret = vm.runInNewContext(code, sandbox); setInterval(function() { console.log(sandbox.foo); // 2秒後以降もhoge }, 500); prototypeが継承されない this が {} オブジェクトに 非同期の変更に追従しない
  39. 39. 新vmモジュール • node_contextfy モジュールをベースにコアに 取り込み。 • 完全に V8::Context を分離。 • 先の不具合を解消。 • WatchDogを導入、timeout 指定も可能に。 var vm = require('vm'); var opts = {timeout: 100}; try { var ret = vm.runInNewContext('while(true){}', {}, opts); } catch(e) { console.log(e); }
  40. 40. tracing モジュール V8のGCイベントとHeap統計情報を取得できます。 その他 AsyncListener: AsyncWrapクラスに引っ掛けてオブジェクト生成、コールバック 起動前後でリスナを起動させるもの。もともとDomainの仕組み に使いたかったが中断。素人は手を出しちゃダメ。 var v8 = require('tracing').v8; console.log('initial:', v8.getHeapStatistics()); v8.on('gc', function(before, after) { console.log('before:', before); console.log('after:', after); }); gc(); // run with --expose-gc option type - mark-sweep-compact - scavenge flags 0: None 2: ConstructRetainedObjectInfos 4: Force timestamp ナノ秒 total_heap_size ヒープサイズ合計 total_heap_size_executable 実行可能なヒープサイズ合計 total_physical_size 物理サイズ合計 used_heap_size 利用中のヒープサイズ heap_size_limit ヒープサイズ制限値 メモリリーク調 査に使ってね
  41. 41. Cluster RoundRobin • 従来のClusterは、複数のプロセスが同時に accept(2) してkernelが割り当てを決定。 • kernel側がコンテキストをなるべく変更しないよう 最適化→処理するプロセスが偏る問題 • Node-v0.12では、親プロセスが、accept(2)して子 供に順番に渡すRoundRobin方式をデフォルトに。 (旧方式も選択可) • cluster.schedulingPolicy にmodeを代入。 • Windowsでは問題があり、未実装。
  42. 42. Cluster Modeの比較・検証する var cluster = require('cluster'), http = require('http'); if (process.argv[2] === 'none') cluster.schedulingPolicy = cluster.SCHED_NONE; var mode = cluster.schedulingPolicy === 1 ? 'None' : 'Round Robin'; var N = 4, results = {}, total = 0; cluster.isMaster ? Master() : Worker(); process.on('result', function() { for(var pid in results) { console.log('pid:', pid, 'requests:' ,results[pid]); } }); function Master() { console.log('cluster.schedulingPolicy:', mode); for(var i = 0; i < N; i++) { cluster.fork().on('message', function(msg) { results[this.process.pid + ''] = msg; if (++total%1000 === 0) process.emit('result'); }); } } function Worker() { var counter = 0; var server = http.createServer(function(req, res) { res.writeHead(200, {'content-type': 'text/plain'}); res.end('Hello World'); process.send(++counter); }).listen(8080, function() { console.log('Listening on pid:' + process.pid); });
  43. 43. 結果 ab -n 1000 http://localhost:8080/ cluster.SCHED_NONE $ node test.js none cluster.schedulingPolicy: None Listening on pid:1831 Listening on pid:1834 Listening on pid:1832 Listening on pid:1836 pid: 1831 requests: 211 pid: 1832 requests: 267 pid: 1834 requests: 260 pid: 1836 requests: 262 cluster.SCHED_RR $ node test.js cluster.schedulingPolicy: Round Robin Listening on pid:1819 Listening on pid:1822 Listening on pid:1820 Listening on pid:1824 pid: 1819 requests: 250 pid: 1820 requests: 250 pid: 1822 requests: 250 pid: 1824 requests: 250 (環境: Ubuntu14.04, kernel-3.13)
  44. 44. その他高速化ネタ • http.ClientRequestの同時接続制限を廃止 • Buffer実装をslaballocator廃止、smalloc化でV8管 理に変更、高速化を達成 • TLS性能の高速化 – Paypalベンチでは2倍程度(AES256-GCM-SHA384) – tlsのネイティブモジュール化、AES-NI対応などの恩恵 • VDSO(Virtual Dynamically linked Shared Objects)利 用による時刻取得のシステムコールを削減(Linux) • マルチコンテキスト化に伴うHeap利用の改善と post GCのオーバヘッドを削減 参考: http://strongloop.com/strongblog/performance-node-js-v-0-12-whats-new/
  45. 45. Any Questions? (special thanks いらすとや http://www.irasutoya.com/ )

×