I'm currently trying to improve a couple of modules regarding performance.
Some of you may know the usage of the walk()
method on collection which is very useful to avoid looping through products directly.
On top of that and thanks to @Vinai, one can also use the collection delete()
method.
But I noticed that Magento 1 native files don't always use any of those methods for deletion.
One of the worst code I've seen is the massDelete()
method from app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php
where products are loaded in a loop before deletion.
foreach ($productIds as $productId) {
$product = Mage::getSingleton('catalog/product')->load($productId);
Mage::dispatchEvent('catalog_controller_product_delete', array('product' => $product));
$product->delete();
}
So I made some performance tests, added some logging calls to check the time taken and the memory usage for 100 products deletion.
Test 1: walk
method
I replaced the original code pasted above with this code:
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('entity_id')
->addIdFilter($productIds)
->walk('delete');
And my results are the following on my crappy dev server (average based on 10 tests):
- Original code: 19.97 seconds, 15.84MB used
- Custom code: 17.12 seconds, 15.45MB used
So for 100 products deletion, my custom code is 3 seconds faster and uses 0.4MB less.
Test 2: Using the collection delete()
method
I replaced the original code with this one:
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('entity_id')
->addIdFilter($productIds)
->delete();
And mind blown here are the results:
- Original code: 19.97 seconds, 15.84MB used
- Custom code: 1.24 seconds, 6.34MB used
So for 100 products deletion, my custom code is 18 seconds faster and uses 9MB less.
As stated in the comments, it seems like this method does not trigger the Magento events (after load, after delete) nor the index/cache flush.
Question
So my question is: is there a reason why the Magento core team did not use the walk('delete')
or event better the collection delete()
method instead of loading products in a loop (which we all know is a very very bad practice) ?
Main goal is to be aware of such key points in case of a module development: is there any particular cases where one can't use the walk
/ collection delete()
method ?
EDIT: the reason is definitely not because of the catalog_controller_product_delete
event being dispatched as the same code can be found in several places (check the massDelete
methods) in Magento core. I've used the example of products to highlight the performance as they are usually the biggest entities
getSingleton()
as performance measure, instead of the obvious collection usage. Oh and it's possible to trigger the event with a collection as well, just not with thewalk()
shortcut.delete()
makes a DELETE query instead of loading the collection and deleting each product. With that one you'll really loose the events.