node.js - javascript thread programming

40
Node.js ででで ででででででで ででででででででで サササササ ササ Shibuya.pm ササ ササ @TAKESAKO

Upload: takesako

Post on 11-Jun-2015

2.526 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Node.js - JavaScript Thread Programming

Node.js で学ぶ マルチスレッドプログラミング入門

サイボウズ・ラボ / Shibuya.pm

竹迫 良範 @TAKESAKO

Page 2: Node.js - JavaScript Thread Programming

Cybozu University 22009/04/06

JavaScript

Page 3: Node.js - JavaScript Thread Programming

sleep のない言語 JavaScript

どうやって実現するか?function sleep(msec) { // CPU_100% var t = (new Date()).getTime()-(-msec); while ( (new Date()).getTime() < t ) {} }function sleep(msec) { // LiveConnect Packages.java.lang.Thread.sleep(msec); }

Page 4: Node.js - JavaScript Thread Programming

クロスブラウザで sleep を実現(無理矢理)

function sleep(msec) { try { // for IE window.showModalDialog( "javascript:document.write('<script>" + "window.setTimeout(function(){window.close()}," + msec + ");<"\/script>');"); } catch (e) { try { // for Firefox, Opera with LiveConnect Packages.java.lang.Thread.sleep(msec); } catch (e) { // for Safari and others var limit = (new Date()).getTime() - (-msec); while ((new Date()).getTime() < limit) {} } } }

Page 5: Node.js - JavaScript Thread Programming

1 秒ごとに表示したい(よくある間違い)

<script>function sleep(msec) { var t = (new Date()).getTime() - (-msec); while ( (new Date()).getTime() < t );}function init() { var body = document.body; sleep(1000); body.innerHTML += "<h1>Hello!</h1>"; sleep(1000); body.innerHTML += "<h2>Hello?</h2>"; sleep(1000); body.innerHTML += "<h3>Hello!?</h3>";};</script><body onload="init()"></body>

Page 6: Node.js - JavaScript Thread Programming

問題1: sleep している間 CPU_100% (><)

Page 7: Node.js - JavaScript Thread Programming

問題2:3秒後にまとめて表示される

Page 8: Node.js - JavaScript Thread Programming

setTimeout で 1 秒ごとに表示する(正解)<script>setTimeout(function(){ var body = document.body; body.innerHTML += "<h1>Hello!</h1>"; setTimeout(function(){ body.innerHTML += "<h2>Hello?</h2>"; setTimeout(function(){ body.innerHTML += "<h3>Hello!?</h3>"; }, 1000); }, 1000);}, 1000);</script>

Page 9: Node.js - JavaScript Thread Programming

setTimeout.html – シングルスレッド+遅延

Page 10: Node.js - JavaScript Thread Programming

Cybozu University 102009/04/06

}, 1000);

}, 1000);}, 1000);

}, 1000);}, 1000);

Page 11: Node.js - JavaScript Thread Programming

Cybozu University 112009/04/06

});});

});});

});

Page 12: Node.js - JavaScript Thread Programming

yield

Page 13: Node.js - JavaScript Thread Programming

yield で 1 秒ごとに表示<!DOCTYPE html><title>Firefox2.0+ only</title><script type="application/javascript;version=1.7">(function(g){var f=arguments.callee;setTimeout( function(){f(g)},g.next())})((function(){ yield (1000); document.body.innerHTML += "<h1>Hello!</h1>"; yield (1000); document.body.innerHTML += "<h2>Hello?</h2>"; yield (1000); document.body.innerHTML += "<h3>Hello!?</h3>";})());</script>

Page 14: Node.js - JavaScript Thread Programming

yield.html – 疑似マルチタスク処理

Page 15: Node.js - JavaScript Thread Programming

やりたいこと = 細かく setTimeout を呼ぶ

// こんな風に書けたらいいなぁ(><)

for (var i = 0; i < 10000000; i++) {// すん//   ごく//  重たい//  処理//    ・・・setTimeout( 次の行 , 0); // ブラウザに処理を戻す

// でもループの中は繰り返したい }   // 終了

Page 16: Node.js - JavaScript Thread Programming

JavaScript 1.7(Firefox 2.0+)

Page 17: Node.js - JavaScript Thread Programming

yield を含む関数は Generator になる

function generator() {for (var i = 1; i <= 1000; i++) {

document.title = i;yield;

}}

var g = generator(); // [object Generator]

// まだ document.title は変更されない

Page 18: Node.js - JavaScript Thread Programming

Generator#next で次の yield まで実行戻る

function generator() {for (var i = 1; i <= 1000; i++) {

document.title = i;yield;

}}

var g = generator(); // [object Generator]g.next(); // document.title = 1;g.next(); // document.title = 2;g.next(); // document.title = 3;

Page 19: Node.js - JavaScript Thread Programming

uncaught exception: [object StopIteration]

function generator() {for (var i = 1; i <= 1000; i++) {

document.title = i;yield;

}}

var g = generator();for (var j = 1; j <= 998; j++) { g.next() }g.next(); // document.title = 999;g.next(); // document.title = 1000;g.next(); // Error: uncaught exception: // [object StopIteration]

Page 20: Node.js - JavaScript Thread Programming

Generator#close

function generator() {for (var i = 1; i <= 1000; i++) {

document.title = i;yield;

}}

var g = generator();for (var j = 1; j <= 998; j++) { g.next() }g.next(); // document.title = 999;g.next(); // document.title = 1000;g.close();

Page 21: Node.js - JavaScript Thread Programming

yield の引数が next() の戻り値になる

function generator() {for (var i = 1; i <= 1000; i++) {

document.title = i;yield   (i);

}}

var g = generator();var r;r = g.next(); // r = 1;r = g.next(); // r = 2;r = g.next(); // r = 3;

Page 22: Node.js - JavaScript Thread Programming

next() の戻り値をチェックしてきちんと終了

function generator() {for (var i = 1; i <= 1000; i++) {

document.title = i;yield   (i);

}yield (-1); // 終了条件

}

var g = generator();var r;do { r = g.next() } while (r > 0); // 1...1000g.close();

Page 23: Node.js - JavaScript Thread Programming

巨大ループ中で setTimeout(f, 0) が呼べる!

function generator() {for (var i = 1; i <= 1000; i++) {

document.title = i;yield   true;

}yield false;

}

function driveGenerator(g) { if (g.next()) { // yield true?

var f = function(){ driveGenerator(g) };setTimeout(f, 0);

} else {g.close(); // yield false

}}

driveGenerator( generator() );

Page 24: Node.js - JavaScript Thread Programming

yield + setTimeout イディオムが完成

(function(g){var f=arguments.callee;var t=g.next(); (t<0) ? g.close():setTimeout(function(){f(g)},t)})((function(){

for (var i = 0; i < 10000; i++) { document.title = i; // 重たい処理 yield (0); // ブラウザに一旦処理を戻す( setTimeout ) } yield (-1); // 終了

})());

Page 25: Node.js - JavaScript Thread Programming

yield すごい !

Page 26: Node.js - JavaScript Thread Programming

  Firefox でしか…

 でも…

Page 27: Node.js - JavaScript Thread Programming

JavaScript1.7 の指定をしないと yield 動かない

<script type="application/javascript;version=1.7">

(function(g){var f=arguments.callee;var t=g.next(); (t<0) ? g.close():setTimeout(function(){f(g)},t)})((function(){

for (var i = 0; i < 10000; i++) { document.title = i; // 重たい処理 yield (0); // ブラウザに一旦処理を戻す( setTimeout ) } yield (-1); // 終了

})());

</script>

Page 28: Node.js - JavaScript Thread Programming

28

Page 29: Node.js - JavaScript Thread Programming

HTML5 関連Web Workers

Page 30: Node.js - JavaScript Thread Programming

HTML5 Web Workers API

main.html worker.js

(3) onmessage = function(e) { var result = e.data + ”!”;

(4) postMessage(result);

(1) var worker = new Worker(“worker.js”);

(2) worker.postMessage(”hello”);

(5) worker.onmessage = function(e) { // DOM 更新処理 window.alert(e.data);

ワーカースレッドの作成

Page 31: Node.js - JavaScript Thread Programming

ワーカスレッドを呼び出す UI スレッド

worker.html

<title>HTML5 Web Workers</title><script>var worker = new Worker("worker.js");

worker.onmessage = function(e){ document.body.innerHTML += e.data;}

worker.postMessage("hello");</script>

Page 32: Node.js - JavaScript Thread Programming

ワーカスレッドの定義(重たい処理を分離)

worker.jsfunction sleep(msec) { var t = (new Date()).getTime() - (-msec); while ( (new Date()).getTime() < t );}//↓ ワーカ側でメッセージを受信したときの処理onmessage = function(e) { sleep(1000); postMessage("<h1>" + e.data + "!</h1>");}

Page 33: Node.js - JavaScript Thread Programming

Web Workers のセキュリティ

Worker スレッドからは

wndow オブジェクトに

触れない!

CPU_100% でも

ブラウザ固まらない!

window.document.write(“hoge”)

UI スレッド

ワーカスレッド

Page 34: Node.js - JavaScript Thread Programming

Firefox, Safari, Chrome で動作

Page 35: Node.js - JavaScript Thread Programming

Cybozu University 352009/04/06

Node.js拡張

できる?

Page 36: Node.js - JavaScript Thread Programming

Cybozu University 362009/04/06

Page 37: Node.js - JavaScript Thread Programming

Cybozu University 372009/04/06

Page 40: Node.js - JavaScript Thread Programming

40