有没有办法加快执行这个递归函数并保持递归?
var printDecreased = function(z) {
console.log(z);
if (z > 0) {
printDecreased(z-1);
}
};
printDecreased(50);
由于这只有一个递归调用,我认为有很多方法可以加速它
答案 0 :(得分:2)
加速功能的一种可能方法是为其添加一点冗余。例如,使用Duff's device我们可以尝试提高函数的性能:
function printDecreasedOptimized(z) {
console.log(z);
if (z > 0) {
switch (z % 8) {
case 0: console.log(--z);
case 7: console.log(--z);
case 6: console.log(--z);
case 5: console.log(--z);
case 4: console.log(--z);
case 3: console.log(--z);
case 2: console.log(--z);
case 1: console.log(--z);
}
(z > 0 && printDecreasedDuff(z));
}
}
function printDecreasedDuff(z) {
console.log(--z);
console.log(--z);
console.log(--z);
console.log(--z);
console.log(--z);
console.log(--z);
console.log(--z);
console.log(--z);
(z > 0 && printDecreasedDuff(z));
}
这个想法是一次执行八次迭代,从而节省了七个函数调用开销的成本。令人惊讶的是,on benchmarking this code我发现这种优化对性能没有太大影响。
我猜测像V8和SpiderMonkey这样的现代JavaScript引擎足够聪明,可以优化这些递归函数。因此,您无需担心此类功能的性能。确实,premature optimization is the root of all evil。BTW,在proper tails calls附近,您的递归函数只会变得更快。
答案 1 :(得分:1)
你可以通过避免if语句来增加速度:
var printDecreased = function(z) {
console.log(z);
(z > 0 && printDecreased(z-1));
};
printDecreased(50);
但增幅很小(约5-10%)
这是如何运作的?
这里的关键字是分支预测。我不会详细介绍分支预测,因为这不是问题所在。最重要的是,分支机构花费了相当多的CPU时间,这意味着,每个如果非常昂贵,如果你想提高大量使用线路的速度,那么尽量省去所有分支机构
最简单的方法是替换 if / else 构造,每个构造只包含三元运算符,而 if 构造只包含一个语句总计由&& 或 || 运算符组成。这些通常比 if s或 if / else 更快。这几乎适用于任何支持这些结构的编程语言。
<强>实施例强>
if (x==y) {
callA();
} else {
callB();
}
可以替换为
(x==y ? callA() : callB());
和
if (x==y) {
callA();
}
可以替换为
(x==y && callA());
或
(x!=y || callA());
这些选项为编译器提供了更好的优化方法,因此可以优化分支预测。
其他可能的优化 到目前为止,这个例子很难被优化,具有给定的限制。由于这是一个微不足道的函数,函数调用开销构成了执行时间的很大一部分。如果你可以用循环替换递归(这在给定的例子中很容易完成),一般来说,你可以加快这个过程的速度。删除递归可以加速大多数编程语言中的函数,因为调用函数通常会花费大量的CPU时间。
答案 2 :(得分:-1)
您可以查看memoize。 Underscore声称它是Useful for speeding up slow-running computations
答案 3 :(得分:-1)
简单地缩短了功能名称。在...创建了一个性能测试 jsperft
var p = function(z) {
console.log(z);
(z > 0 && p(z-1));
};