2012-05-11 15 views
13

Mi script importa un archivo de Excel en una base de datos de productos para actualizar cantidades de productos nuevos, etc.¿Cómo puedo borrar la memoria mientras ejecuto un script PHP largo? intentado unset()

Tengo un problema de memoria y he tratado de aumentar el límite de memoria al máximo (800MB +). Intenté desarmar las variables para liberar la memoria entre los bucles pero todavía me quedo sin memoria. He intentado establecer el tiempo de espera en infinito, pero definitivamente es un problema de memoria.

msg de error del archivo de registro: Fatal error: Permitido el tamaño de la memoria de 851443712 bytes agotado (intentó asignar 71 bytes)

Ninguno de la secuencia de comandos está contenida en una función. Si creo el bucle for principal dentro de una función y llamo repetidamente a esa función ¿eso ayudará a la recolección de basura y a borrar la memoria? Cualquier ayuda u orientación será apreciada.

script de importación:

error_reporting(E_ALL & ~E_NOTICE); 
ini_set('memory_limit', '812M'); 
set_time_limit(0); 

/* Config Start */ 
define('BasePath', '/home/xxxxx/public_html'); 
define('CfgMagentoPath',     BasePath); 
define('CfgCategoryMapDBxls',     BasePath."/xxxx/Shdddddd.xls"); 
define('CfgVenderDBxls',     BasePath."/xxxx/xxxxxx.xls"); 
define('CfgReportEmail',     "[email protected]"); 
/* Config End */ 

require_once(CfgMagentoPath . '/app/Mage.php'); 
Mage::app(); 
//$app = Mage::app('default'); 
//Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID); 
require_once(BasePath.'/xxxxx/xxxx/libs/mage.func-inc.php'); 
require_once(BasePath.'/xxxxx/xxxxx/libs/excel-read.class.php'); 

//Alert Arrays 
$AAnotmapped  = array(); 
$AAnewproducts = array(); 
$AApriceupdated = array(); 
$AAimgerror   = array(); 
$PriceErrors  = array(); 

$SkipCat = false; 

//Create Mapped Cats - In Magento 

$excel = new ExcelReader(CfgCategoryMapDBxls,"UTF-8"); 
$CM = $excel->getWorksheetData('Sheet1'); 
if(!$SkipCat){ 
    echo "======== Generating Catagory Maps ===========\n\n"; 
    CatMap_Create($CM); 
    echo "======== ============================== ===========\n\n"; 
} 

//Start Item Read 
$excel = new ExcelReader(CfgVenderDBxls,"UTF-8"); 
$IT = $excel->getWorksheetData('New_DATA'); 
$ITcnt = 0; 
$ITtotal = count($IT); 

foreach($IT as $ItemRow){ 
    $ITcnt++; 

    $cSKU     = $ItemRow['ITEM']; 
    $cProductName = Clean_Data($ItemRow['ALTSHORTDESC']); 
    $cCatName   = Clean_Data($ItemRow['CATEGORY']); 
    $cManuf     = Clean_Data($ItemRow['MANUFACTURER']); 
    $cShortDesc   = Clean_Data($ItemRow['SHORTDESC']); 
    $cLongDesc   = Clean_Data($ItemRow['LONGDESC']); 
    $cUPC      = Prod_GetUPC($ItemRow['UPC'], $ItemRow['ALTUPC']); 
    $cStockQty   = $ItemRow['QTY']; 
    $cWeight    = Prod_GetWeight($ItemRow['WEIGHT'], $ItemRow['ALTWEIGHT']); 
    $cPrice     = Prod_FigurePrice($ItemRow['COST'], $ItemRow['MSRP'], $ItemRow['MAP']); 
    $cCost     = $ItemRow['COST']; 


    //Locate Catagory Map Magento ID 
    $mCatId = CatMap_Search($CM, $ItemRow['CATEGORY']); 

    //Now Create Product 
    if($mCatId > 0 && $cProductName != ""){ 

     echo date("m.d.y g:i a")."\t($ITcnt/$ITtotal) Working On: " . $cProductName . " - SKU: $cSKU\n"; 
     $ProdID = Prod_GetIDfromSKU($cSKU); 


     if($ProdID > 0){ 
      if(Prod_Update($ProdID, $cCost, $cStockQty, $cWeight, $cUPC)){ 
       echo "Updated: $cProductName\n"; 
       $ITindex++; 
      } 
     }else{ 
      Prod_Create($cSKU, $cProductName, $cManuf, $cPrice, $cCost, $cWeight, $cShortDesc, $cLongDesc, $cStockQty, $cUPC, $mCatId); 
      echo "Created: $cProductName to Catagory: $mCatId\n"; 
      echo "$cShortDesc\n\n"; 
      $ProdID = Prod_GetIDfromSKU($cSKU); 
     } 


     if($cPrice <= $cCost){ 
      array_push($PriceErrors, "[$cSKU] $cProductName > Cost: $cCost | Price: $cPrice"); 
      echo "Price Lower than Cost : Auto Inactive : Cost: $cCost | Price: $cPrice\n"; 
     } 

     Prod_AddImg($ProdID, $cSKU); 

    } 


    unset($ItemRow, $ProdID, $cSKU, $cProductName, $cManuf, $cPrice, $cCost, $cWeight, $cShortDesc, $cLongDesc, $cStockQty, $cUPC, $mCatId); 
    echo "\n"; 

} 


echo "======== Disabling 0 Product Catagories ===========\n\n"; 
Cat_Disable_Empty($CM); 
echo "======== ============================== ===========\n\n"; 

unset($CM, $IT, $excel); 

//array_push($AAnotmapped, 'Cat not Mapped'); 
//array_push($AApriceupdated, '### Price Updated'); 
//array_push($AAimgerror , 'Image Error'); 

Send_Status_Email(); 

Mage_Reindex(); 


echo date("m.d.y g:i a")."\tCompleted\n\n"; 

//print_r($AAnotmapped); 

//print_r($AApriceupdated); 

//print_r($AAimgerror); 
+0

Desarmado las variables justo antes de reasignarlos se gana nada aquí. ¿Qué versión de PHP? ¿Qué hay dentro de algunas de estas funciones? ¿Tu lector de Excel está tirando datos ansioso o flojo? ¿Se le acaba la memoria antes de llegar a mage_reindex? –

+0

Hola Cory, la versión de PHP es 5.2.9, el script pasa aproximadamente ~ 3700-4000 productos antes de que muera. No estoy seguro si es flojo/ansioso y sí se queda sin memoria antes de llamar a mage_reindex. –

Respuesta

17

Uso de las funciones.
Use $var = null; en lugar de unset($var);. Desarmado simplemente mata la referencia variable.


Como se ha mencionado en este comment:

When you are using unset, the memory will only be freed whenever garbage collector decides, but when you are setting a variable to a different value (null in this case), then you might get some memory freed of course with the cost of CPU.

+1

¿Qué pasa con "matar la referencia variable"? – deceze

+8

@deceze Killing is wrong wrong, man ... –

+5

@Michael Por eso es muy bien llamado * unset *, no 'kill_with_extreme_prejudice()'. :) – deceze

2

Incluso cuando se utiliza funciones, se podría esperar que el recolector de basura para limpiar todo en el ámbito de la función cuando la función devuelve .. Esto no es una garantía y el uso de funciones incluso pueden funcionar en su contra si está luchando contra el uso de la memoria. Debido al alcance, php tiene que crear copias de las variables pasadas como parámetros, que solo se sumarán al uso de la memoria. Podrías ver las referencias que pasan.

El recolector de basura solo liberará memoria cuando haya ciclos de CPU disponibles. Por lo general, en bucles no tendrá una oportunidad, por lo que intentará hacer esto después del bucle, en cuyo caso podría ser demasiado tarde.

Sin embargo, puede forzar al recolector de basura a hacer su ronda llamando al gc_collect_cycles.

También usted puede intentar depurar el código utilizando memory_get_usage()

+0

Pasar por referencia es una buena idea para los parámetros de datos grandes que puede estar pasando. Solo tenga cuidado de no editar ese parámetro en la función si no tenía la intención de hacerlo. Además, la depuración es siempre ... una buena idea. – arikin

Cuestiones relacionadas