Domanda

sto cercando di modificare i dati dei clienti in massa (un paio di migliaia di record) e di Magento mantiene a corto di memoria disponibile per eseguire lo script.

Dopo alcuni test con memory_get_usage() il colpevole sembra essere il metodo $customer->save() che sembra prendere 5M di memoria per ogni salvataggio, ma non rilasciarlo quando fatto.

Di conseguenza, quando il ciclo attraverso un paio di migliaia di dischi è in esecuzione di memoria.

Ecco quello che ho provato finora:

$customer->clearInstance()

unset($customer)

Questo non sembra però aiuto.

Di seguito è riportato il mio codice:

public function createCustomerAddress($customerAddressData, $email){
     $customer = Mage::getModel('customer/customer');

     $customer->setWebsiteId(Mage::app()->getWebsite()->getId());
     $customer->loadByEmail($email);

     $address   = Mage::getModel('customer/address');

     $address->addData($customerAddressData);
     $customer->addAddress($address);
     unset($address);
     try{
         $customer->save();
     }catch (Exception $e){
         var_dump($customerAddressData);
         var_dump($e->getMessage());
     }
    echo "\n" . "Before unsetting \n" . memory_get_usage() . "\n";
    $customer->clearInstance();
    unset($customer);
    echo "\n" . "After  \n" . memory_get_usage() . "\n";  // no difference than before
}

Qualsiasi aiuto sarebbe molto apprezzato.

P.S. Io non sono sicuro se la funzione clearInstance() (nel Mage_Core_Model_Abstract) fa niente, se qualcuno ha una certa comprensione in questo sarebbe molto apprezzato se condiviso:)

È stato utile?

Soluzione

Credo che questo è legato ad un problema di core di PHP, che non è facilmente risolto senza ampie modifiche ai file core Magento.

L'unico modo per ottenere questo fatto sta utilizzando una soluzione:

Vi propongo:

a. Se questo viene chiamato dal browser, vorrei fare una chiamata ajax separata, come @Julien Lacal raccomandato nella sua risposta.

b. Se questo è tutto l'essere fatto lato server, vorrei spezzare questo fino a due script, con 1. uno che itera sulla lista dei clienti esistenti, e 2. quella che chiama la funzione createCustomerAddress, utilizzando params postali. Il secondo script dovrebbe quindi essere chiamato con CURL dal primo script, in modo che ogni istanza delle seconde piste di script in isolamento, e non è influenzato dalla perdita di memoria.

Altri suggerimenti

Memoria viene rilasciato solo una volta non ci sono riferimenti a tale variabile / oggetto. Ho il sospetto - e permetterà di modificare la mia risposta, una volta confermata, che il sistema di eventi in Magento passa un'istanza del modello per l'osservatore, e quindi c'è un riferimento ad esso nella memoria

.

Ma questo è un problema ben documentato. (Quello che ho commentato nel 2011 http://www.magentocommerce.com/boards/viewthread/ 26561 / ).

Credo che questo sia un problema noto su tutte le piattaforme e le versioni di Magento. unset() o clearInstance() non avranno alcun effetto. Mage::getModel() trapelata la memoria in tutti i casi che ho incontrato (clienti, prodotti, ordini, ecc). L'unico modo per aggirare che ho trovato è quello di utilizzare una collezione, invece, se possibile (potrebbe non essere applicabile per voi), quando si tratta di un gran numero di creazioni di oggetti. Quando il processo è completato, sarà rilasciato la memoria.

Siete a corto di memoria? Questo di solito non è un problema se non si è. Se si esegue fuori la memoria, forse, si può provare a rompere il processo di massa in esecuzioni separate nel proprio interno. Se questo è in uno script di shell, allora sarebbe facile da rompere in su. Basta creare due o più file ed eseguire una dopo l'altra con le gamme predefinito di entity_ids clienti.

Una buona soluzione potrebbe essere quella di costruire il proprio modulo di amministrazione per l'importazione di massa dei clienti, e lo hanno utilizzare le chiamate Ajax a un controller per importare dati in gruppi più piccoli. In questo modo non sarà a corto di memoria perché sarà lanciare un nuovo processo ogni volta che si effettua che Ajax chiamata invece di allocare la memoria costantemente a causa della Mage::getModel('customer/address')

Sembra che ho trovato una grande perdita di memoria quando si chiama Model::save()

Dopo che l'elemento è stato salvato nel database v'è il seguente codice nel metodo citato:

$this->_getResource()->addCommitCallback(array($this, 'afterCommitCallback'))

In questo modo il modello viene aggiunto al parametro statici $_commitCallbacks. Il metodo verrà rimosso se il livello transazione è impostato a zero soltanto.

Per risolvere questo o aggiungere il seguente codice per il proprio modello di risorse:

public function addCommitCallback($callback)
{
    return $this;
    //return parent::addCommitCallback($callback);
}

Questo funziona solo per un tipo di modello di risorse, è necessario fare questo per tutti i modelli di risorse che vengono aggiornati di frequente nel vostro ciclo. Un inconveniente è che il metodo afterCommitCallback() del modello non viene mai chiamato.

Altro (migliore) possibilità è quella di sovrascrivere i metodi commit() e rollback() e rimuovere il modello dalla variabile in ogni caso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a magento.stackexchange
scroll top