鍍金池/ 問答/PHP/ php foreach中一個變量重復賦值是否會不斷消耗內存?

php foreach中一個變量重復賦值是否會不斷消耗內存?

                   foreach ($arr as $key => $value) {
                       $res = $this->querydata($value);
                       $data = array('res'=>$res);
                       M('test')->add($data);
                   }
               

如上demo,$res會獲取到一個很大的數(shù)據(jù),然后存入數(shù)據(jù)庫中,這個foreach循環(huán)次數(shù)很多,而且每次循環(huán)我都沒有unset($res),因為我認為重復賦值不會重新消耗內存。。。但好像被打臉,報錯了:
圖片描述

說超出內存限制128M了。。。請教大神foreach中一個變量的重復賦值會不會一直消耗內存? ( ps: querydata()這個方法有用到curl請求,在這個循環(huán)里也就是不斷的請求數(shù)據(jù))
更新:真實完整代碼如下

// 獲取到最新分頁的酒店id
           $arr = $this->queryHotelIdList();
           if($arr['retrunCode'] == '000'){
               for($i=$play['cur_page'];$i<=$arr['bussinessResponse']['totalPage'];$i++){
                   $page = $i;
                   $arr = $this->queryHotelIdList($page);
                   M('play')->where("id={$play['id']}")->save(array('cur_page'=>$page));

                   // 將1000個id的數(shù)組拆分100個10個為一組的二維數(shù)組
                   $ten_arr = array_chunk($arr['bussinessResponse']['hotelIds'], 10);
                   // 循環(huán)這個二維數(shù)組,每一次循環(huán)獲取10家酒店的基本信息,轉json存為一條記錄
                   foreach ($ten_arr as $key => $value) {
                       $res = $this->queryHotelInfo($value);
                       if($res['retrunCode'] == '000'){
                           $data = [];
                           $data['page'] = $page;
                           $data['json_data'] = json_encode($res['bussinessResponse']['hotelInfos']);
                           $titan_data_model->add($data);
                           unset($data);

                       }else{
                           // 失敗則將這10個酒店id記錄下來
                           $failed_ids = implode(',',$value);
                           $data = [];
                           $data['hotel_ids'] = $failed_ids;
                           $data['error_msg'] = $res['retrunMsg'];
                           $data['page'] = $page;
                           $titan_fail_hotel_ids_model->add($data);
                       }
                       unset($res);

                       $memory = memory_get_usage();
                       echo intval($memory/1024);
                       echo "<br>";
                       ob_flush();
                       flush();
                   }
                   
                // 睡眠30秒,以保證不超過300/分鐘的請求次數(shù)限制
                sleep(30);

               }
            
           }
 里面的queryHotelIdList和queryHotelInfo都是一個封裝好的curl請求,返回一個較大的數(shù)據(jù),但不會超過1M
回答
編輯回答
墨小白

前段時間遇到一個無限級分類的問題,為了避免一直消耗內存,賦值過之后的變量就用unset銷毀了.

2017年12月22日 09:54
編輯回答
苦妄

變量重復賦值不會增加內存消耗,當變量被重新賦值為另一個值時,之前的引用計數(shù)會被清除,并釋放掉相應的內存
然后重新賦值為新的值并分配內存,可能是$res = $this->querydata($value);返回的數(shù)據(jù)集過大導致超出內存限制
============================更新=========================
看了TP M方法的源碼,同一個對象僅會實例化一次不會重復實例化
建議貼完整代碼

function M($name='', $tablePrefix='',$connection='') {
    static $_model  = array();
    if(strpos($name,':')) {
        list($class,$name)    =  explode(':',$name);
    }else{
        $class      =   'Think\\Model';
    }
    $guid           =   (is_array($connection)?implode('',$connection):$connection).$tablePrefix . $name . '_' . $class;
    if (!isset($_model[$guid]))
        $_model[$guid] = new $class($name,$tablePrefix,$connection);
    return $_model[$guid];
}
2017年10月28日 04:58
編輯回答
心悲涼

可以使用memory_get_usage();測試一波

2018年1月3日 12:47
編輯回答
艷骨
foreach ($arr as $key => $value) {
    $res = ...
}

沒有使用引用,應該不會 導致內存爆。
隨便寫個測試

$variable = explode(' ', str_repeat('m ', 1024));
$usage = memory_get_usage();
foreach ($variable as $key => $value) {
    $str = str_repeat('k', 1024*1024*50);
}

echo (memory_get_usage() - $usage)/1024/1024 . PHP_EOL;

1024個數(shù)組 foreach,每次賦值 給一個變量 50M 的字符串

λ php test.php
52.000022888184
2017年2月3日 02:14