我目前正在尝试改进有关性能的几个模块。
你们中有些人可能知道集合方法的用法,walk()
这对于避免直接遍历产品非常有用。
最重要的是,感谢@Vinai,我们也可以使用collection delete()
方法。
但是我注意到Magento 1本机文件并不总是使用这些方法中的任何一种进行删除。
一个我见过的最糟糕的代码是massDelete()
从方法app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php
,其中产品在删除之前的循环加载。
foreach ($productIds as $productId) {
$product = Mage::getSingleton('catalog/product')->load($productId);
Mage::dispatchEvent('catalog_controller_product_delete', array('product' => $product));
$product->delete();
}
因此,我进行了一些性能测试,添加了一些日志记录调用,以检查删除100个产品所花费的时间和内存使用情况。
测试1:walk
方法
我用以下代码替换了上面粘贴的原始代码:
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('entity_id')
->addIdFilter($productIds)
->walk('delete');
在我糟糕的开发服务器上的结果如下(基于10个测试的平均值):
- 原始代码:19.97秒,已使用15.84MB
- 自定义代码:17.12秒,已使用15.45MB
因此,对于100种产品的删除,我的自定义代码加快了3秒,而占用的内存少了0.4MB。
测试2:使用收集delete()
方法
我用以下代码替换了原始代码:
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('entity_id')
->addIdFilter($productIds)
->delete();
和记吹这里的结果:
- 原始代码:19.97秒,已使用15.84MB
- 自定义代码:1.24秒,已使用6.34MB
因此,对于100种产品的删除,我的自定义代码加快了18秒,而占用的内存减少了9MB。
如评论中所述,该方法似乎不会触发Magento事件(加载后,删除后),也不会触发索引/缓存刷新。
题
所以我的问题是:Magento核心团队为什么没有使用walk('delete')
or事件更好的收集delete()
方法而不是循环加载产品(我们都知道这是非常非常糟糕的做法)吗?
主要目标是在开发模块时要注意这些关键点:在某些特殊情况下,不能使用walk
/收集delete()
方法吗?
编辑:原因绝对不是因为catalog_controller_product_delete
事件被调度,因为可以massDelete
在Magento核心的多个位置(检查方法)找到同一代码。我以产品为例来强调性能,因为它们通常是最大的实体
delete()
进行DELETE查询,而不是加载集合并删除每个产品。有了这个,您将真正松开事件。
getSingleton()
作为性能度量的用法,而不是明显的集合用法。哦,也可以通过集合来触发事件,只是不能通过walk()
快捷方式来触发。