Зараз я намагаюся покращити пару модулів щодо продуктивності.
Деякі з вас, можливо, знають використання walk()методу колекціонування, що дуже корисно, щоб уникнути розгортання продуктів безпосередньо.
Крім того, завдяки @Vinai, можна також скористатися 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,84 МБ
- Спеціальний код: 17,12 секунди, використано 15,45 МБ
Тож для видалення 100 продуктів мій спеціальний код швидше на 3 секунди і менше на 0,4 МБ.
Тест 2: Використання delete()методу збирання
Я замінив оригінальний код цим:
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('entity_id')
->addIdFilter($productIds)
->delete();
І розум, вибуханий ось такі результати:
- Оригінальний код: 19,97 секунди, використано 15,84 МБ
- Спеціальний код: 1,24 секунди, використано 6,34 Мб
Тож для видалення 100 продуктів мій спеціальний код швидше на 18 секунд і менше на 9 Мб.
Як зазначено в коментарях, схоже, що цей метод не запускає події Magento (після завантаження, після видалення), а також індекс / кеш-пам'ять.
Питання
Отже, моє запитання: чи є причина, чому основна команда Magento не використала метод walk('delete')збирання або подію краще, delete()а не завантажувати продукти в цикл (який ми всі знаємо, дуже погана практика)?
Головною метою є усвідомлення таких ключових моментів у разі розробки модуля: чи є конкретні випадки, коли не можна використовувати метод walk/ collection delete()?
EDIT: причина, безумовно, не в тому, що catalog_controller_product_deleteподія розсилається, оскільки один і той же код можна знайти в декількох місцях (перевірити massDeleteметоди) в Magento core. Я використав приклад продуктів, щоб виділити продуктивність, оскільки вони, як правило, є найбільшими об'єктами
delete()робить запит DELETE замість завантаження колекції та видалення кожного продукту. З цим ви дійсно втратите події.
getSingleton()як міри продуктивності замість очевидного використання колекції. О, і можливо, ініціювати подію також колекцією, тільки неwalk()ярликом.