Зараз я намагаюся покращити пару модулів щодо продуктивності.
Деякі з вас, можливо, знають використання 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()
ярликом.