PHP ไม่เพียงพอด้วย CDataProviderIterator (Yii)

ฉันมีปัญหาหน่วยความจำไม่เพียงพอกับสคริปต์ PHP ของฉันบนกรอบงาน Yii ฉันได้พยายามที่จะทำการดีบักไม่น้อย ฉันใช้ CDataProviderIterator เพราะเอกสาร Yii กล่าวถึงสิ่งนี้:

ตัวอย่างเช่น รหัสต่อไปนี้จะวนซ้ำผู้ใช้ที่ลงทะเบียนทั้งหมด (ผู้ใช้คลาสบันทึกที่ใช้งานอยู่) โดยที่หน่วยความจำไม่หมด แม้ว่าจะมีผู้ใช้หลายล้านคนในฐานข้อมูลก็ตาม

รหัสนี้วนซ้ำมากกว่า 1.5 ล้านบันทึก และหน่วยความจำไม่เพียงพอในความพยายาม ฉันกำลังมองหาความช่วยเหลือว่าทำไมมันถึงทำเช่นนี้ ขอบคุณ!

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;
}

person Sloganho    schedule 15.04.2016    source แหล่งที่มา
comment
แก้ไขด่วนในขณะที่ฉันพยายามสร้าง ini_set นี้ใหม่ ('memory_limit', '-1');   -  person Midhun    schedule 15.04.2016
comment
คุณกำลังแปลง $iterator เป็นอาร์เรย์ดังนั้นมันจะต้องมี ram เพิ่ม! ฉันคิดว่านั่นคือสิ่งที่ทำให้เกิดปัญหา   -  person Midhun    schedule 15.04.2016
comment
คุณแก้ปัญหานี้ไหม?   -  person Midhun    schedule 16.04.2016


คำตอบ (1)


ฉันเชื่อว่าคุณกำลังพยายามแปลง CDataProviderIterator เป็นอาร์เรย์ Php ดังนั้นในการวางอาเรย์คุณต้องมีหน่วยความจำเพิ่ม

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

นี่เป็นการตั้งค่าการใช้ ram เพื่อการใช้งานสูงสุด

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

นี่จะตั้งค่าการใช้งาน RAM เป็น 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));
    }   
}

และ

person Midhun    schedule 15.04.2016
comment
ดังนั้นฉันจึงไม่ได้พยายามแปลง CDataProviderIterator เป็นอาร์เรย์ php ฉันกำลังแปลงแต่ละระเบียนที่วนซ้ำเป็นอาร์เรย์ ในความเป็นจริง สิ่งนี้ควรรักษาหน่วยความจำได้เนื่องจากวิธีที่ CDataProviderIterator ไม่เก็บวัตถุทั้งหมดในหน่วยความจำ ในกรณีของฉัน มันจะเก็บโมเดลอ็อบเจ็กต์ไว้ในหน่วยความจำครั้งละ 200 รายการเท่านั้น จากนั้นมันจะดรอปวัตถุเหล่านั้น ฉันลองวิธีแก้ปัญหาของคุณแล้ว และตอนนี้ฉันก็ไม่ได้รับการตอบกลับ คำถามหลักของฉันคือเหตุใดจึงใช้หน่วยความจำมาก ทั้งที่ในความเป็นจริงควรใช้หน่วยความจำน้อยลงตามการอ้างสิทธิ์ในเอกสารประกอบ - person Sloganho; 15.04.2016
comment
เนื่องจากดูเหมือนว่าคุณกำลังพยายามจัดเก็บอาร์เรย์ 1.5 ล้านอาร์เรย์ไว้ภายใน $model_as_array - person georaldc; 15.04.2016
comment
ใช่ ฉันเห็นสิ่งนั้น แต่คุณกำลังทำอะไรกับ $model_as_array; - person Midhun; 15.04.2016
comment
ฉันกำลังพยายามจัดเก็บอ็อบเจ็กต์ 1.5 ล้านอ็อบเจ็กต์ไว้ในอาร์เรย์ $model_as_array สิ่งที่ฉันทำกับ $model_as_array คือการแปลงเป็น JSON และส่งกลับไปยังไคลเอนต์ การตั้งค่าขีดจำกัดหน่วยความจำแบบนั้นดูเหมือนจะไม่ใช่แนวปฏิบัติที่ดีสำหรับฉัน ฉันลองแล้ว แต่มันก็ไม่ได้ผล ฉันพบวิธีแก้ปัญหาในการแปลงอาร์เรย์เป็น JSON ขณะที่ฉันไปโดยเรียก unset บนวัตถุหลังจากที่ฉันแปลงมันเพื่อรักษาหน่วยความจำ วิธีนี้ใช้งานได้และรักษาหน่วยความจำไว้จริงแทนที่จะเปลี่ยนขีดจำกัดหน่วยความจำ ขอบคุณสำหรับความช่วยเหลือของคุณ - person Sloganho; 16.04.2016
comment
เยี่ยมมาก คุณสามารถแบ่งปันโค้ดตัวอย่างสำหรับโซลูชันของคุณเพื่อให้ชุมชนได้รับประโยชน์ด้วย โปรดเพิ่มเป็นคำตอบ - person Midhun; 16.04.2016