2011-11-26 56 views
2

我有一个递归函数来遍历11M数据库记录,一次1000。当它接近9M时停止。当我在每1000条记录后显示get_memory_usage()时,我确认了记忆问题。深层递归内存泄漏 - 取消设置fopen资源?

功能的工作原理是这样的:

<? 
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服务器。
  • 我试着取消设置不在全局范围内的每个已定义变量。
  • 我似乎无法解决的唯一问题是打开资源。
  • 每次迭代内存大小增加大约400k。

回答

2

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

建立第二个功能,并重新安排一个使你可以这样做(伪代码):

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

即从get_data_block返回$id,给它一个无效的值,如果没有更多的处理必须完成。您不必担心堆栈框架堆积如此。

+0

我觉得很愚蠢。非常感谢。有时候我看不到树木。 –

2

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

PHP显然不会,所以在某些时候你会得到一个堆栈溢出。尝试重写您的代码以代替使用循环,或者一个处理队列来迭代。