2016-01-02 167 views
2

我正在寻找我写的递归算法中的问题。在递归函数中调用堆栈大小:最大调用堆栈大小低于预期

该算法会在某些输入中抛出RangeError: Maximum call stack size exceeded(在Chrome中)错误。但我追踪的调用堆栈大小只有6k-9k。

This testfrom this SO answer)表示Chrome中的最大调用堆栈大小约为42k。


运行一些测试后,我发现,在递归函数有争论似乎降低了可用的调用堆栈大小:

带参数:调用堆栈大小超出了〜31K( Chrome浏览器,在〜15K边)

var recursionA = function(a, b) { 
    count++; 
    if (count < 100000) { 
    recursionA(a, b); 
    } 
} 

没有参数:调用堆栈大小超出了〜42K(铬,〜16.5k上边缘)

var recursionB = function() { 
    count++; 
    if (count < 100000) { 
    recursionB(); 
    } 
} 

See fiddle here

  1. 任何人都可以解释,为什么可用的调用堆栈大小是显著降低,当函数被调用的参数。
  2. 由于我的递归函数需要2个参数:我如何利用浏览器的最大调用堆栈大小?
  3. 是否有其他因素可能会降低可用的调用堆栈大小?
+0

'a'和'b'应该参加堆栈IMO的一部分。每次你用这些参数调用函数时,它们都被作为堆栈一部分的值复制。 – MinusFour

+0

但他们不会立即从堆栈中删除? – jHilscher

+1

只有在递归结束后才会发生,因为没有足够的空间。 – MinusFour

回答

0
  1. 堆栈的大小的字节一些数,而不是一些函数的调用数。添加到函数调用中的每个参数都会消耗一些内存,所以可用的堆栈较少;
  2. 见叫
1

功能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)); 
    
  • 相关问题