2016-04-15 4 views
0

YiiフレームワークでPHPスクリプトのメモリ不足が発生しています。私はかなりのデバッグを試みました。 Yiiのドキュメントはそれについてこれを言うので、私はCDataProviderIteratorを使用しています:PHPがCDataProviderIterator(Yii)でメモリ不足になる

たとえば、次のコードでは、何百万人があっても、メモリ不足に実行せずに、すべての登録ユーザー(アクティブレコードクラスのユーザー)を反復処理しますデータベース内のユーザーの数。

このコードは、約150万レコードを繰り返し処理し、メモリ不足になります。私はこれをやっている理由の助けを探しています。ありがとう!

public function foo($model, $relations) { 
    $dataProvider = new CActiveDataProvider($model, array('criteria' => $model->dbCriteria)); 
    $iterator = new CDataProviderIterator($dataProvider, 200); 
    $this->modelsToArray($iterator, $relations, $model_as_array = array()); 
} 

public function modelsToArray($model, $relations, $model_as_array = array()) { 
    $preparedRelations = $this->prepareRelations($relations); 
    if (is_null($model)) 
    { 
     return array(); 
    } 
    $model_as_array = array(); 
    if (get_class($model) === 'CDataProviderIterator') { 
     foreach ($model as $row) { 
      $model_as_array[] = $this->modelsToArrayHelper($preparedRelations, $row); 
     } 
    } 
    else { 
     $model_as_array[] = $this->modelsToArrayHelper($preparedRelations, $model); 
    } 

    return $model_as_array; 
} 

private function modelsToArrayHelper($relations, $listOfModels) { 
    $listOfArrayModels = array(); 

    if(!is_array($listOfModels)){ 
     return $this->modelToArrayHelper($listOfModels, $relations); 
    } 
    foreach ($listOfModels as $index => $model) 
    { 
     $listOfArrayModels[$index] = $this->modelToArrayHelper($model, $relations); 
    } 
    return $listOfArrayModels; 
} 

private function modelToArrayHelper($model, $relations){ 
    $model_as_array = $this->processAttributes($model); 
    foreach ($relations as $relationIndex => $relation) 
    { 
     $relationName = is_string($relationIndex) ? $relationIndex : $relation; 
     if(empty($model->$relationName)) 
      continue; 
     if ($model->relations()[$relationName][0] != CActiveRecord::STAT) 
     { 
      $subRelations = is_array($relation) ? $relation : array(); 
      $model_as_array[$relationName] = $this->modelsToArrayHelper($subRelations, $model->$relationName); 
     } 
     else 
     { 
      $model_as_array[$relationName] = $model->$relationName; 
     } 
    } 

    return $model_as_array; 
} 
+0

これを再作成しようとしている間にすばやく修正します。 ini_set( 'memory_limit'、 '-1'); – Midhun

+0

$ iteratorを配列に変換しているので、より多くのRAMが必要になります! 私はそれが問題を引き起こしているものと思う – Midhun

+0

これを解決しましたか? – Midhun

答えて

1

私はCDataProviderIteratorをPHP配列に変換しようとしていると思います。 ので、配列を配置するために、あなたがより多くのメモリを必要とする

ini_set('memory_limit', '-1'); 

これはあなたのコードを作ることができ、最大使用量にラムの使用

ini_set('memory_limit', '512M'); 

が、これは512 Mbの

にRAM使用量を設定し、設定しますあなたがあまりにも多くのラムを使用していないことを確認するためにこのようにしてください。

public function foo($model, $relations) { 
    $dataProvider = new CActiveDataProvider($model, array('criteria' => $model->dbCriteria)); 
    $iterator = new CDataProviderIterator($dataProvider, 200); 
    $preparedRelations = $this->prepareRelations($relations); 
    foreach ($iterator as $row) { 
      print_r ($this->modelsToArrayHelper($preparedRelations, $row)); 
    } 
} 

+0

私はCDataProviderIteratorをPHP配列に変換しようとしていません。私はそれが配列に反復処理する各レコードを変換しています。実際には、これは、CDataProviderIteratorがすべてのオブジェクトをメモリに格納しないため、メモリを保持するはずです。私の場合は、一度に200個のモデルオブジェクトをメモリに格納してからドロップします。私はあなたの解決策を試してみましたが、今はただ応答を返さないだけです。私の主な質問は、実際にはドキュメンテーションの主張に基づいてメモリを減らす必要があるときに、これが非常に多くのメモリを占有している理由です。 – Sloganho

+1

$ model_as_arrayの中に150万の配列を格納しようとしているようです。 – georaldc

+0

はい、私はそれを見ることができますが、あなたは$ model_as_arrayで何をしていますか? – Midhun