Attualmente sto cercando di migliorare un paio di moduli per quanto riguarda le prestazioni.
Alcuni di voi potrebbero conoscere l' utilizzo del walk()
metodo sulla raccolta, che è molto utile per evitare di scorrere direttamente i prodotti.
Inoltre, grazie a @Vinai, è anche possibile utilizzare il delete()
metodo di raccolta .
Ma ho notato che i file nativi di Magento 1 non usano sempre nessuno di questi metodi per la cancellazione.
Uno dei peggiori codici che ho visto è il massDelete()
metodo da app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php
cui i prodotti vengono caricati in un ciclo prima dell'eliminazione .
foreach ($productIds as $productId) {
$product = Mage::getSingleton('catalog/product')->load($productId);
Mage::dispatchEvent('catalog_controller_product_delete', array('product' => $product));
$product->delete();
}
Quindi ho effettuato alcuni test delle prestazioni, ho aggiunto alcune chiamate di registrazione per verificare il tempo impiegato e l'utilizzo della memoria per l'eliminazione di 100 prodotti.
Test 1: walk
metodo
Ho sostituito il codice originale incollato sopra con questo codice:
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('entity_id')
->addIdFilter($productIds)
->walk('delete');
E i miei risultati sono i seguenti sul mio server di sviluppo scadente (media basata su 10 test):
- Codice originale: 19,97 secondi, 15,84 MB utilizzati
- Codice personalizzato: 17,12 secondi, 15,45 MB utilizzati
Quindi, per la cancellazione di 100 prodotti, il mio codice personalizzato è 3 secondi più veloce e usa 0,4 MB in meno.
Test 2: utilizzo del delete()
metodo di raccolta
Ho sostituito il codice originale con questo:
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('entity_id')
->addIdFilter($productIds)
->delete();
E la mente soffiata qui sono i risultati:
- Codice originale: 19,97 secondi, 15,84 MB utilizzati
- Codice personalizzato: 1,24 secondi, 6,34 MB utilizzati
Quindi, per la cancellazione di 100 prodotti, il mio codice personalizzato è più veloce di 18 secondi e utilizza 9 MB in meno.
Come indicato nei commenti, sembra che questo metodo non attivi gli eventi Magento (dopo il caricamento, dopo l'eliminazione) né il flush dell'indice / cache.
Domanda
Quindi la mia domanda è: c'è un motivo per cui il core team di Magento non ha usato walk('delete')
o evitato meglio il delete()
metodo di raccolta invece di caricare i prodotti in un ciclo (che sappiamo tutti è una pessima pratica)?
L'obiettivo principale è essere consapevoli di tali punti chiave in caso di sviluppo di un modulo: ci sono casi particolari in cui non è possibile utilizzare il metodo walk
/ collection delete()
?
EDIT: il motivo non è sicuramente dovuto al catalog_controller_product_delete
fatto che l' evento viene inviato in quanto lo stesso codice può essere trovato in diversi punti (controlla i massDelete
metodi) nel core di Magento. Ho usato l'esempio dei prodotti per evidenziare le prestazioni in quanto di solito sono le entità più grandi
delete()
effettua una query DELETE invece di caricare la raccolta e cancellare ogni prodotto. Con quello perderai davvero gli eventi.
getSingleton()
come misura delle prestazioni, invece dell'ovvio utilizzo della raccolta. Oh ed è possibile attivare l'evento anche con una raccolta, ma non con lawalk()
scorciatoia.