Atualmente, estou tentando melhorar alguns módulos em relação ao desempenho.
Alguns de vocês devem saber o uso do walk()
método na coleta, o que é muito útil para evitar a repetição direta dos produtos.
Além disso, e graças ao @Vinai, também é possível usar o delete()
método de coleta .
Mas notei que os arquivos nativos do Magento 1 nem sempre usam qualquer um desses métodos para exclusão.
Um dos piores códigos que eu já vi é o massDelete()
método no app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php
qual os produtos são carregados em um loop antes da exclusão .
foreach ($productIds as $productId) {
$product = Mage::getSingleton('catalog/product')->load($productId);
Mage::dispatchEvent('catalog_controller_product_delete', array('product' => $product));
$product->delete();
}
Então fiz alguns testes de desempenho, adicionei algumas chamadas de log para verificar o tempo gasto e o uso de memória para exclusão de 100 produtos.
Teste 1: walk
método
Substituí o código original colado acima por este código:
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('entity_id')
->addIdFilter($productIds)
->walk('delete');
E meus resultados são os seguintes no meu servidor de desenvolvimento de baixa qualidade (média com base em 10 testes):
- Código original: 19.97 segundos, 15.84MB usado
- Código personalizado: 17.12 segundos, 15.45MB usado
Portanto, para a exclusão de 100 produtos, meu código personalizado é 3 segundos mais rápido e usa 0,4 MB a menos.
Teste 2: Usando o delete()
método de coleta
Substituí o código original por este:
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('entity_id')
->addIdFilter($productIds)
->delete();
E a mente soprada aqui estão os resultados:
- Código original: 19.97 segundos, 15.84MB usado
- Código personalizado: 1,24 segundos, 6,34 MB usados
Portanto, para a exclusão de 100 produtos, meu código personalizado é 18 segundos mais rápido e usa 9 MB a menos.
Conforme declarado nos comentários, parece que esse método não aciona os eventos Magento (após o carregamento, após a exclusão) nem o fluxo de índice / cache.
Questão
Portanto, minha pergunta é: existe uma razão pela qual a equipe principal do Magento não usou walk('delete')
melhor o delete()
método de coleta ou evento , em vez de carregar produtos em um loop (que todos sabemos que é uma prática muito, muito ruim)?
O objetivo principal é estar ciente desses pontos-chave no caso de um desenvolvimento de módulo: existem casos específicos em que não é possível usar o método walk
/ collection delete()
?
EDIT: o motivo definitivamente não é por causa do catalog_controller_product_delete
envio do evento, pois o mesmo código pode ser encontrado em vários locais (verifique os massDelete
métodos) no núcleo do Magento. Usei o exemplo de produtos para destacar o desempenho, pois geralmente são as maiores entidades
delete()
faz uma consulta DELETE em vez de carregar a coleção e excluir cada produto. Com isso, você realmente perderá os eventos.
getSingleton()
como medida de desempenho, em vez do uso óbvio da coleção. Ah, e também é possível disparar o evento com uma coleção, mas não com owalk()
atalho.