递归函数中的调用堆栈大小:最大调用堆栈大小低于预期
Call Stack size in recursive functions: Maximum call stack size is lower than expected
我正在寻找我编写的递归算法中的问题。
此算法会在某些输入上抛出 RangeError: Maximum call stack size exceeded
(在 Chrome 中)错误。但是我追踪到的调用栈大小只有 6k-9k 左右。
This test (from this SO answer)表示在Chrome.
中最大调用栈大小约为42k
经过 运行 一些测试后,我发现,在递归函数上使用参数似乎会降低可用的调用堆栈大小:
带参数: ~31k 上超出了调用堆栈大小(Chrome,Edge 上~15k)
var recursionA = function(a, b) {
count++;
if (count < 100000) {
recursionA(a, b);
}
}
没有参数: ~42k 上的调用堆栈大小超出(Chrome,Edge 上的~16.5k)
var recursionB = function() {
count++;
if (count < 100000) {
recursionB();
}
}
- 谁能解释一下,为什么在使用参数调用函数时可用的调用堆栈大小明显变小。
- 由于我的递归函数需要 2 个参数:我如何利用浏览器的最大调用堆栈大小?
- 还有其他因素可能会减少可用调用堆栈的大小吗?
- 堆栈的大小是字节,而不是函数调用。您添加到函数调用中的每个参数都会消耗一些内存,因此可用堆栈更少;
- 见上1
- 调用函数中的变量
我只想创建另一个递归函数来调用该递归函数并拆分持续时间,这样您就不会最大化堆栈。这是一个 "callStackOptimizer" 的例子,我刚刚为一个复杂而昂贵的 fizzbuzz 游戏写了一个更实用的不可变风格来向你展示我的意思。
"use strict";
const isDivisibleBy = divisor => number => number % divisor === 0;
const isDivisibleBy3 = isDivisibleBy(3);
const isDivisibleBy5 = isDivisibleBy(5);
const isDivisibleBy3And5 = number => isDivisibleBy5(number) && isDivisibleBy3(number);
const rules = (bool1, bool2, bool3) => (value1, value2, value3) => number => {
switch (true){
case bool1(number):
return value1;
break;
case bool2(number):
return value2;
break;
case bool3(number):
return value3;
break;
default:
return number;
}
};
const gameConditions = rules(
isDivisibleBy3And5,
isDivisibleBy3,
isDivisibleBy5
);
const fizzBuzzResults = gameConditions(
"FizzBuzz",
"Fizz",
"Buzz"
);
const game = duration => value => (action, array = []) => {
if (duration > 0){
const nextValue = action(value);
return game(duration - 1)(value + 1)(action, array.concat(nextValue))
}
else {
return array
}
};
const callStackOptimizer = (duration, times = Math.ceil(duration/10000), result = []) => rules =>{
if (times > 0){
const value = duration/times;
const round = game(value)(value * times - value + 1)(rules);
return callStackOptimizer(duration - value , times - 1, result.concat(round))(rules)
}
else {
return result;
}
};
const playFizzBuzz = duration => callStackOptimizer(duration)(fizzBuzzResults);
console.log(playFizzBuzz(100000));
我正在寻找我编写的递归算法中的问题。
此算法会在某些输入上抛出 RangeError: Maximum call stack size exceeded
(在 Chrome 中)错误。但是我追踪到的调用栈大小只有 6k-9k 左右。
This test (from this SO answer)表示在Chrome.
中最大调用栈大小约为42k经过 运行 一些测试后,我发现,在递归函数上使用参数似乎会降低可用的调用堆栈大小:
带参数: ~31k 上超出了调用堆栈大小(Chrome,Edge 上~15k)
var recursionA = function(a, b) {
count++;
if (count < 100000) {
recursionA(a, b);
}
}
没有参数: ~42k 上的调用堆栈大小超出(Chrome,Edge 上的~16.5k)
var recursionB = function() {
count++;
if (count < 100000) {
recursionB();
}
}
- 谁能解释一下,为什么在使用参数调用函数时可用的调用堆栈大小明显变小。
- 由于我的递归函数需要 2 个参数:我如何利用浏览器的最大调用堆栈大小?
- 还有其他因素可能会减少可用调用堆栈的大小吗?
- 堆栈的大小是字节,而不是函数调用。您添加到函数调用中的每个参数都会消耗一些内存,因此可用堆栈更少;
- 见上1
- 调用函数中的变量
我只想创建另一个递归函数来调用该递归函数并拆分持续时间,这样您就不会最大化堆栈。这是一个 "callStackOptimizer" 的例子,我刚刚为一个复杂而昂贵的 fizzbuzz 游戏写了一个更实用的不可变风格来向你展示我的意思。
"use strict";
const isDivisibleBy = divisor => number => number % divisor === 0;
const isDivisibleBy3 = isDivisibleBy(3);
const isDivisibleBy5 = isDivisibleBy(5);
const isDivisibleBy3And5 = number => isDivisibleBy5(number) && isDivisibleBy3(number);
const rules = (bool1, bool2, bool3) => (value1, value2, value3) => number => {
switch (true){
case bool1(number):
return value1;
break;
case bool2(number):
return value2;
break;
case bool3(number):
return value3;
break;
default:
return number;
}
};
const gameConditions = rules(
isDivisibleBy3And5,
isDivisibleBy3,
isDivisibleBy5
);
const fizzBuzzResults = gameConditions(
"FizzBuzz",
"Fizz",
"Buzz"
);
const game = duration => value => (action, array = []) => {
if (duration > 0){
const nextValue = action(value);
return game(duration - 1)(value + 1)(action, array.concat(nextValue))
}
else {
return array
}
};
const callStackOptimizer = (duration, times = Math.ceil(duration/10000), result = []) => rules =>{
if (times > 0){
const value = duration/times;
const round = game(value)(value * times - value + 1)(rules);
return callStackOptimizer(duration - value , times - 1, result.concat(round))(rules)
}
else {
return result;
}
};
const playFizzBuzz = duration => callStackOptimizer(duration)(fizzBuzzResults);
console.log(playFizzBuzz(100000));