【问题标题】:Deep recursion memory leak - unset a fopen resource?深度递归内存泄漏 - 取消设置 fopen 资源?
【发布时间】:2012-01-06 21:04:00
【问题描述】:

我有一个递归函数来迭代超过 11M 的数据库记录,一次 1000 条。当它接近 9M 时它停止了。当我在每 1000 条记录后显示 get_memory_usage() 时,我对内存问题的假设得到了证实。

函数的工作原理如下:

<?
get_data_block();

function get_data_block($id=0);
{
    //open a csv file for writing
    $packages_sorted_csv=fopen("./csv/packages_sorted.csv", "a");

    //get 1000 records and process them
    //$unsorted = array of 1000 records from database
    foreach($unsorted as $row);
    {
        $ct++;
        $id++;
        //$packages_sorted = array of processed data

        //write output
        fputcsv($packages_sorted_csv, $packages_sorted);
    }
    fclose($packages_sorted_csv);

    if($ct==1000)
    {
        unset($unsorted);
        echo 'Mem usage: '.memory_get_usage();
        get_data_block($id);    //call the function again
    }else{
        //finished
    }
}

?>

有没有人有关于如何使用递归函数释放所有资源的提示? ...或者有没有办法再次调用同一个函数,这样它就不会被自己调用?

注意事项:

  • 我必须将数据分块以释放繁忙的 mysql 服务器。
  • 我已尝试取消设置不在全局范围内的所有已定义变量。
  • 我似乎唯一无法取消设置的是 fopen 资源。
  • 每次迭代内存大小增加约 400k。

【问题讨论】:

    标签: php memory-management memory-leaks recursion


    【解决方案1】:

    从您发布的代码来看,递归似乎不是正确的方法。

    构建第二个函数并重新排列那个函数,以便您可以执行类似(伪代码)的操作:

    while (!$done) {
      $id = get_data_block($id);
      $done = // determine if finished or not
    }
    

    即从get_data_block 返回$id,如果不需要进行更多处理,则给它一个无效值。您不必担心这样堆积的堆栈帧。

    【讨论】:

    • 我觉得自己很笨。非常感谢。有时我就是只见树木不见森林。
    【解决方案2】:

    一种好的编程语言应该识别尾递归并将其转化为隐式循环。

    PHP 显然没有,所以在某些时候你会遇到堆栈溢出。尝试重写代码以使用循环,或者例如要迭代的处理队列。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-27
      • 1970-01-01
      • 2016-07-07
      • 2012-09-29
      • 1970-01-01
      相关资源
      最近更新 更多