【问题标题】:How much memory cost call of recursive function PHP递归函数PHP调用多少内存成本
【发布时间】:2014-03-02 22:00:51
【问题描述】:

我有递归函数:

function find($index, &$itemsCounts, &$amountsSums, $deep)

在这个函数中我再次调用它:

find($index, &$itemsCounts, &$amountsSums, $deep+1)

最大深度为 182,分配内存的峰值为 751MB...我不明白在那个递归调用中是什么占用了这么多内存...

谁能解释一下?有人知道在堆栈上存储一个调用需要多少内存吗? 谢谢

编辑: 函数看起来像:

private function findChod($index, &$itemsCounts, &$amountsSums, $deep){
    if($amountsSums['a'] > $this->upperLimit) return;
      $check_string = "";

      if($deep > $this->maxDeep) $this->maxDeep = $deep;

    foreach ($this->x[$index]['a'] as $key => $item) {
      $check_string = $check_string." ".$itemsCounts[$key];
    }

    if(isset($this->memo[$check_string]))
      return;

    $this->memo[$check_string] = 1;

     $a = "asda;"
     $b = "asda;"
     $c = "asda;"
     $d = "asda;"
     $e = "asda;"
     $f = "asda;"

    if() return;

    if(){
      if(){
        $this->compareWithBest($amountsSums, $itemsCounts, abs($fatsDifference)+abs($protsDifference)+abs($carbsDifference));
      }
    }

    unset($a);
    unset($b);
    unset($c);

    unset($d);
    unset($e);
    unset($f);

    foreach ($this->x[$index]['items'] as $key => $item) {
      $amountsSums['a'] +=  $item['a'] * $item['unit'];
      $amountsSums['b'] +=  $item['b'] * $item['unit'] ;
      $amountsSums['c'] +=  $item['c'] * $item['unit'];
      $amountsSums['d'] +=  $item['d'] * $item['unit'];
      $itemsCounts[$key]++;

      $this->find($index, $itemsCounts, $amountsSums, $deep+1);

      $amountsSums['a'] -=  $item['a'] * $item['unit'];
      $amountsSums['b'] -=  $item['b'] * $item['unit'];
      $amountsSums['c'] -=  $item['c'] * $item['unit'];
      $amountsSums['d'] -=  $item['d'] * $item['unit'];
      $itemsCounts[$key]--;
    }
  }

备忘录的峰值为 1 900 000 项... 我正在使用 php 5.5.3

EDIT2: 我发现变量 memo 需要 cca 307MB

EDIT3: 我重写了我的算法,所以我根本不需要内存......

【问题讨论】:

  • 你能显示find($args,...)函数的内容吗?顺便问一下你的 PHP 版本是什么。
  • 这很大程度上取决于find 函数在每次调用时在做什么
  • 除非您使用旧的 PHP4 调用时间,否则不推荐使用按引用传递。您使用find($index, $itemsCounts, $amountsSums, $deep+1) 进行递归。这并不能解释您的内存使用情况,因此您应该编辑问题并添加 find 的完整定义。
  • 是的,但我没有使用按引用传递的调用时间...我仍然不明白这里是什么占用了这么多内存...
  • unset($check_string)(在递归调用之前)有帮助吗? $itemsCounts 也可能变大。嗯,您必须进行调试并查看内存使用情况。我不确定 PHP 是否可以做到这一点。 xdebug 可能会有所帮助。

标签: php memory-management recursion


【解决方案1】:

PHP 的数组与经典数组相去甚远。它是一种实现链表和哈希表的数据结构。有很多开销明显反映在内存消耗中。我不知道关于它们的任何实现细节,但它仅 1900000 *(10 字节索引 + 4 字节值)占用 300MB 的事实意味着您不能在 PHP 中使用大型数组。

我最近才了解到,PHP 确实提供了对消耗更少内存的经典数组的访问。 PHP 称之为SplFixedArray。但这对您没有帮助,因为您确实需要哈希映射的功能。

【讨论】:

  • 您确定是这种情况吗...我的循环长度为 5,但如果我是对的,那么它会调用函数 find sychnronous... 这意味着它将等待该函数的返回...等等堆栈实际上可以只是这182个函数调用
  • 不确定,只是猜测。使用调试器查看发生了什么。但我认为你的堆栈很可能会被这些调用填满。每个 find() 调用 5 次 find()(调用 5 次 find(),...)。这会迅速爆发。
  • 我编辑了我的答案,以适应这种高深度可能不是堆栈的问题,但更可能是堆的问题。
  • 我会纠正你:它不会在 2^182 的路上爆炸,因为如果你看一下代码 itemCounts 只有 4 个索引,而 memo 有 1 900 000 个索引,每个索引都是1号...
  • 显然$memo 爆炸了。 1 的值在理想情况下应该需要 2 到 4 个字节。但是您的索引 ($check_string) 会占用大量内存。
猜你喜欢
  • 2013-09-09
  • 2017-03-15
  • 2010-09-10
  • 2013-06-15
  • 2018-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多