cliente Magento Salva perdita di memoria
-
22-10-2019 - |
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:)
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_id
s 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.