加速javascript中的递归函数
有没有办法加速这个递归函数的执行并保持它的递归性加速javascript中的递归函数,javascript,recursion,Javascript,Recursion,有没有办法加速这个递归函数的执行并保持它的递归性 var printDecreased = function(z) { console.log(z); if (z > 0) { printDecreased(z-1); } }; printDecreased(50); 因为它只有一个递归调用,所以我认为没有很多方法可以加快它的速度您可以通过避免像这样的if语句来稍微提高速度: var printDecreased = function(z) {
var printDecreased = function(z) {
console.log(z);
if (z > 0) {
printDecreased(z-1);
}
};
printDecreased(50);
因为它只有一个递归调用,所以我认为没有很多方法可以加快它的速度您可以通过避免像这样的if语句来稍微提高速度:
var printDecreased = function(z) {
console.log(z);
(z > 0 && printDecreased(z-1));
};
printDecreased(50);
但增幅很小(约5-10%)
这是怎么回事?
这里的关键字是分支预测。我不会详细讨论分支预测,因为这不是问题所在。底线是,分支占用了相当多的CPU时间,这意味着,如果每个都非常昂贵,并且如果您想提高大量使用的行的速度,那么请尽量省去所有分支
最简单的方法是用三元运算符替换每边只包含一条语句的if/else构造,用&&或|运算符替换总共只包含一条语句的if构造。一般来说,这些速度比ifs或if/elses快得多。这几乎可以应用于任何支持这些结构的编程语言
示例
if (x==y) {
callA();
} else {
callB();
}
可以替换为
(x==y ? callA() : callB());
及
可以用
(x==y && callA());
或
这些选项为编译器提供了关于如何优化的更好线索,因此它可以优化分支预测
其他可能的优化
在给定的限制条件下,很难对该示例进行比目前更好的优化。由于这是一个非常简单的函数,因此函数调用开销占执行时间的很大一部分。如果可以用循环替换递归(在给定的示例中很容易做到),一般来说,也可以大大加快过程。在大多数编程语言中,删除递归会加快函数的速度,因为调用函数通常会花费大量的CPU时间。您可以通过避免下面的if语句来稍微提高速度:
var printDecreased = function(z) {
console.log(z);
(z > 0 && printDecreased(z-1));
};
printDecreased(50);
但增幅很小(约5-10%)
这是怎么回事?
这里的关键字是分支预测。我不会详细讨论分支预测,因为这不是问题所在。底线是,分支占用了相当多的CPU时间,这意味着,如果每个都非常昂贵,并且如果您想提高大量使用的行的速度,那么请尽量省去所有分支
最简单的方法是用三元运算符替换每边只包含一条语句的if/else构造,用&&或|运算符替换总共只包含一条语句的if构造。一般来说,这些速度比ifs或if/elses快得多。这几乎可以应用于任何支持这些结构的编程语言
示例
if (x==y) {
callA();
} else {
callB();
}
可以替换为
(x==y ? callA() : callB());
及
可以用
(x==y && callA());
或
这些选项为编译器提供了关于如何优化的更好线索,因此它可以优化分支预测
其他可能的优化
在给定的限制条件下,很难对该示例进行比目前更好的优化。由于这是一个非常简单的函数,因此函数调用开销占执行时间的很大一部分。如果可以用循环替换递归(在给定的示例中很容易做到),一般来说,也可以大大加快过程。在大多数编程语言中,删除递归会加快函数的速度,因为调用函数通常会花费大量的CPU时间。您可以看看。下划线声称它对加速运行缓慢的计算非常有用,您可以看一下。下划线声称它有助于加速运行缓慢的计算一种可能的加速函数的方法是增加一点冗余。例如,使用我们可以尝试提高函数的性能:
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));
}
其思想是一次执行八次迭代,从而节省七次函数调用的开销。令人惊讶的是,我发现这种优化对性能没有多大影响
我推测,像V8和SpiderMonkey这样的现代JavaScript引擎足够聪明,可以优化此类递归函数。因此,您不必担心这些函数的性能。的确
顺便说一句,在即将到来的时候,递归函数只会变得更快。加快函数速度的一种可能方法是为其添加一点冗余。例如,使用我们可以尝试提高函数的性能:
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));
}
其思想是一次执行八次迭代,从而节省七次函数调用的开销。令人惊讶的是,我发现这种优化对性能没有多大影响
我推测,像V8和SpiderMonkey这样的现代JavaScript引擎足够聪明,可以优化此类递归函数。因此,您不必担心这些函数的性能。的确
顺便说一句,递归函数的速度将越来越快。只需缩短函数名即可。在上创建了性能测试
只需缩短函数名。在上创建了性能测试
尝试<代码>返回(z-1)代码>。还有,你是如何测量速度的。虽然,将其转换为循环,这将是最好的加速。是的,循环会更好,但要求是保持递归。。但我认为递归是最好的way@thefourtheye-这不会导致无限循环/堆栈溢出吗?删除console.log它会提高性能