åˆã‚ã«æ–ã£ã¦ãŠãã¾ã™ãŒã€ä»Šå›žã®èª¿æŸ»ã¯ã€node v0.11.5 (Linux)ã§è©¦ã—ãŸã‚‚ã®ã§ã€ä»–ã®ç’°å¢ƒã§ã¯ç•°ãªã‚‹ã‹ã‚‚ã—れã¾ã›ã‚“。ã•らã«ã€ä»Šå¾Œã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚¢ãƒƒãƒ—ã«ã‚ˆã£ã¦ã¯å…¨ãç•°ãªã‚‹çµæžœã¨ãªã‚‹ã“ã¨ã‚‚å分ã‚りãˆã¾ã™ã€‚ã”æ³¨æ„を。
ES6ã«generatorsãŒå…¥ã‚‹ã¨ã®ã“ã¨ã§ã€JavaScriptã§continuationãŒä½¿ãˆãªã„ã‹ãªãã¨æ€ã£ã¦ã„ãŸè‡ªåˆ†ã¨ã—ã¦ã¯ã€èˆˆå‘³ã‚’æŒã¡ã¾ã—ãŸã€‚
ã¡ãªã¿ã«ã€generator, coroutine, continuationã®é †ã«è¨˜è¿°åŠ›ãŒä¸ŠãŒã‚‹ãã†ã§ã™ã€‚ã“ã¡ã‚‰ãŒå‚考ã«ãªã‚‹ã‹ã‚‚ã—れã¾ã›ã‚“。
ã•ã¦ã€generatorsã®èª¬æ˜Žã¯ä»–ã«ä»»ã›ã‚‹ã¨ã—ã¦ã€ã„ããªã‚Šã‚³ãƒ¼ãƒ‰ã§ã™ã€‚
function* es6_generator() {
yield 1;
yield 2;
yield 3;
yield 4;
return 5;
}
ã“れを複数回実行ã—ã¦æ™‚間を計測ã™ã‚‹ã‚³ãƒ¼ãƒ‰ã¯ã“ã¡ã‚‰ã€‚
console.time('es6_generator');
for (i = 0; i < 1000000; i++) {
iterator = es6_generator();
obj = {};
while (!obj.done) {
obj = iterator.next();
}
}
console.timeEnd('es6_generator');
å®Ÿè¡Œçµæžœã¯ã€
es6_generator: 360ms
ã§ã—ãŸã€‚ã†ã¡ã®ãƒžã‚·ãƒ³ã¯éžåŠ›ãªã®ã§ã€æœ€è¿‘ã®ãƒžã‚·ãƒ³ãªã‚‰ã‚‚ã£ã¨é€Ÿã„ã‹ã‚‚ã—れã¾ã›ã‚“。
ã“れã¨åŒç‰ã®ã‚³ãƒ¼ãƒ‰ã‚’generatorsを使ã‚ãšã«æ›¸ãã¨ã©ã†ãªã‚‹ã§ã—ょã†ã‹ã€‚ãŠãらãã€
function hand_generator1() {
var iterator = {};
iterator.next = function() {
iterator.next = function() {
iterator.next = function() {
iterator.next = function() {
iterator.next = function() {
return {value: 5, done: true};
};
return {value: 4, done: false};
};
return {value: 3, done: false};
};
return {value: 2, done: false};
};
return {value: 1, done: false};
};
return iterator;
}
ã“ã‚“ãªæ„Ÿã˜ã«ãªã‚‹ã®ã§ã—ょã†ã€‚
ã“れをåŒã˜ã‚ˆã†ã«å®Ÿè¡Œã—ãŸã‚‰ã€
hand_generator1: 4529ms
ã¨ãªã‚Šã¾ã—ãŸã€‚ã“れãŒç‰ä¾¡ãªã‚³ãƒ¼ãƒ‰ãªã®ã‹ã¯å•題ã§ã™ãŒã€
å°‘ãªãã¨ã‚‚hand_generator1
ã®ã‚ˆã†ã«æ›¸ãよりã¯ã€
es6_generator
ã®æ–¹ãŒé€Ÿã„ã¨ã†ã“ã¨ã§ã™ã。
ã—ã‹ã—ã€ã“ã®å˜ç´”ãªä¾‹ã ã¨functionをイテレーション毎ã«ç”Ÿæˆã™ã‚‹å¿…è¦ã¯ãªãã¦ã€ã‚‚ã£ã¨åŠ¹çŽ‡çš„ã«æ›¸ã‘ã¾ã™ã€‚
function hand_generator2() {
var array = [1, 2, 3, 4, 5];
var index = 0;
var iterator = {
next: function() {
return {value: array[index++], done: array.length <= index};
}
};
return iterator;
}
ã“ã®å ´åˆã®å®Ÿè¡Œçµæžœã¯ã€
hand_generator2: 265ms
ã¨ãªã‚Šã¾ã—ãŸã€‚es6_generator
ã¨æ¯”ã¹ã¦ã©ã¡ã‚‰ãŒèªã¿ã‚„ã™ã„ã¨æ€ã†ã‹ã¯äººæ¬¡ç¬¬ã§ã—ょã†ã‹ã€‚ã§ãã‚‹ã“ã¨ãŒé•ã†ã®ã§æ¯”較ã®å¯¾è±¡ã«ãªã‚‰ãªã„ã§ã™ãŒã€‚
ã•ã¦ã€å°‘ã—話ãŒã‚„ã‚„ã“ã—ããªã‚Šã¾ã™ãŒã€ã‚‚ã¨ã‚‚ã¨ã¯æœ«å°¾å†å¸°ã‚’やりãŸã‹ã£ãŸã®ã§ã™ã€‚末尾å†å¸°ã®èª¬æ˜Žã¯ä»–ã«ä»»ã›ã‚‹ã¨ã—ã¦ã€factorialã‚’generatorsを使ã£ã¦æ›¸ã„ã¦ã¿ã¾ã—ãŸã€‚
function fact_tail_loop1(x) {
var fact_tail_sub = function* (x, r) {
if (x === 0) {
return r;
} else {
yield fact_tail_sub(x - 1, x * r);
}
};
var c = fact_tail_sub(x, 1);
var d = {};
while (!d.done) {
d = c.next();
c = d.value;
}
return d.value;
}
ã“れを見ã¦ã€ãµãƒ¼ã‚“ã€ã¨ã‹ã€ãŠãƒ¼ã€ã¨ã‹æ€ã‚ãªã„å ´åˆã¯ã€ã“ã®å…ˆã‚’èªã‚“ã§ã‚‚ã¤ã¾ã‚‰ãªã„ã‹ã‚‚ã—れã¾ã›ã‚“。
実行コードã¯ã“ã¡ã‚‰ã€‚
console.time('fact_tail_loop1');
console.log(fact_tail_loop1(3));
console.log(fact_tail_loop1(5));
console.log(fact_tail_loop1(10));
console.log(fact_tail_loop1(100));
console.log(fact_tail_loop1(1000));
console.log(fact_tail_loop1(10000));
console.log(fact_tail_loop1(100000));
console.log(fact_tail_loop1(1000000));
console.timeEnd('fact_tail_loop1');
実行ã™ã‚‹ã¨æ¬¡ã®ã‚ˆã†ã«ãªã‚Šã¾ã—ãŸã€‚
6
120
3628800
9.332621544394418e+157
Infinity
Infinity
Infinity
Infinity
fact_tail_loop1: 217ms
Infinityã«ãªã£ã¦ã¾ã™ãŒã€ã¡ã‚ƒã‚“ã¨è¨ˆç®—ã¯ã—ã¦ã„るよã†ã§ã™ã€‚ã¡ãªã¿ã«æ™®é€šã®å†å¸°ã‚„properã§ãªã„末尾å†å¸°ã®å ´åˆã¯ã€æœ€å¾Œã®æ–¹ã¯è¨ˆç®—ã§ããšã«ã‚¨ãƒ©ãƒ¼ã«ãªã‚Šã¾ã™ã€‚
ã•ã¦ã€generatorsを使ã‚ãªã„ã§æ›¸ãç›´ã—ã¦ã¿ã¾ã—ãŸã€‚
function fact_tail_loop2(x) {
var fact_tail_sub = function(x, r) {
return {
next: function() {
if (x === 0) {
return {
value: r,
done: true
};
} else {
return {
value: fact_tail_sub(x - 1, x * r),
done: false
};
}
}
};
};
var c = fact_tail_sub(x, 1);
var d = {};
while (!d.done) {
d = c.next();
c = d.value;
}
return d.value;
}
åŒã˜ã‚ˆã†ã«å®Ÿè¡Œã™ã‚‹ã¨ã€
6
120
3628800
9.332621544394418e+157
Infinity
Infinity
Infinity
Infinity
fact_tail_loop2: 796ms
ã«ãªã‚Šã¾ã—ãŸã€‚ã—ã‹ã—ã€ã“ã®ã‚³ãƒ¼ãƒ‰ã¯ã‚ªãƒ–ジェクトã®ç”ŸæˆãŒå¤šã™ãŽã¾ã™ã€‚改良版ã¯ã“ã¡ã‚‰ã€‚
var LoopCont = function(f) {
this.f = f;
};
function fact_tail_loop3(x) {
var fact_tail_sub = function(x, r) {
if (x === 0) {
return r;
} else {
return new LoopCont(function() {
return fact_tail_sub(x - 1, x * r);
});
}
};
var c = fact_tail_sub(x, 1);
while (c instanceof LoopCont) {
c = c.f();
}
return c;
}
ã“れを実行ã™ã‚‹ã¨ã€
6
120
3628800
9.332621544394418e+157
Infinity
Infinity
Infinity
Infinity
fact_tail_loop3: 63ms
ã¨ãªã‚Šã¾ã—ãŸã€‚ã„ã‹ãŒã§ã—ょã†ã€‚
ç§è¦‹ã§ã™ãŒã€generatorsã®ãƒ‘フォーマンスã¯çŠ¶æ³æ¬¡ç¬¬ã¨ã„ã£ãŸã¨ã“ã‚ã§ã—ょã†ã‹ã€‚v8ã®æœ€é©åŒ–ãŒé€²ã‚ã°ã€æ§˜ã€…ãªã‚±ãƒ¼ã‚¹ã§æ”¹å–„ã•れるã‹ã¨æ€ã‚れã¾ã™ã€‚
ã—ã‹ã—ã€generatorsを使ã£ã¦æœ«å°¾å†å¸°ã‚„continuationを実装ã§ããªã„ã‹ãªãã€ã¨æœŸå¾…ã—ãŸã®ã§ã¡ã‚‡ã£ã¨æ®‹å¿µã§ã—ãŸã€‚ã‚„ã£ã±ã‚Šè¨€èªžãƒ¬ãƒ™ãƒ«ã§ã‚µãƒãƒ¼ãƒˆã—ã¦ã»ã—ã„ã§ã™ã。
個人的ã«ã¯ã€yield expressionã¯æ§‹é€ ãŒåˆ†ã‹ã‚Šã«ããæ„Ÿã˜ã€å¥½ãã«ãªã‚Œãã†ã«ãªã„ã®ã§ã€ç›´æŽ¥ä½¿ã†ã“ã¨ã¯ãªã„ã‹ã¨æ€ã„ã¾ã™ã€‚ã†ã¾ãéš è”½ã—ã¦ãれるライブラリãŒã‚れã°ã„ã„ã®ã‹ã‚‚ã—れã¾ã›ã‚“。
ã“ã“ã¾ã§èªã‚“ã§ãã‚ŒãŸæ–¹ã¯ã€
https://github.com/dai-shi/continuation.js
ã«ã‚‚興味をæŒã£ã¦ã„ãŸã ã‘ã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™ã®ã§ã€
よã‚ã—ã‘れã°ã”覧ãã ã•ã„。