Obecnie próbuję ulepszyć kilka modułów pod względem wydajności.
Niektórzy z was mogą znać użycie walk()
metody zbierania, która jest bardzo przydatna, aby uniknąć bezpośredniego przechodzenia między produktami.
Ponadto dzięki @Vinai można również użyć delete()
metody zbierania .
Zauważyłem jednak, że rodzime pliki Magento 1 nie zawsze używają żadnej z tych metod usuwania.
Jednym z najgorszych kodów, jakie widziałem, jest massDelete()
metoda, z app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php
której produkty są ładowane w pętli przed usunięciem .
foreach ($productIds as $productId) {
$product = Mage::getSingleton('catalog/product')->load($productId);
Mage::dispatchEvent('catalog_controller_product_delete', array('product' => $product));
$product->delete();
}
Przeprowadziłem więc testy wydajności, dodałem kilka wywołań logowania, aby sprawdzić czas i zużycie pamięci na usunięcie 100 produktów.
Test 1: walk
metoda
Zastąpiłem oryginalny kod wklejony powyżej tym kodem:
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('entity_id')
->addIdFilter($productIds)
->walk('delete');
A moje wyniki są następujące na moim gównianym serwerze deweloperskim (średnia z 10 testów):
- Kod oryginalny: 19,97 sekundy, użyto 15,84 MB
- Kod niestandardowy: 17,12 sekund, użyto 15,45 MB
Tak więc przy usuwaniu 100 produktów mój niestandardowy kod jest 3 sekundy szybszy i zużywa 0,4 MB mniej.
Test 2: przy użyciu delete()
metody zbierania
Zamieniłem oryginalny kod na ten:
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('entity_id')
->addIdFilter($productIds)
->delete();
A umysł jest zdumiony :
- Kod oryginalny: 19,97 sekundy, użyto 15,84 MB
- Kod niestandardowy: 1,24 sekundy, użyto 6,34 MB
Tak więc dla usunięcia 100 produktów mój niestandardowy kod jest 18 sekund szybszy i zużywa 9 MB mniej.
Jak stwierdzono w komentarzach, wygląda na to, że ta metoda nie wyzwala zdarzeń Magento (po załadowaniu, po usunięciu) ani opróżnieniu indeksu / pamięci podręcznej.
Pytanie
Moje pytanie brzmi zatem: czy istnieje powód, dla którego główny zespół Magento nie zastosował metody walk('delete')
zbierania lub zdarzenia, delete()
zamiast ładować produkty w pętli (co, jak wszyscy wiemy, jest bardzo złą praktyką)?
Głównym celem jest świadomość takich kluczowych punktów w przypadku rozwoju modułu: czy są jakieś szczególne przypadki, w których nie można użyć metody walk
/ collection delete()
?
EDYCJA: powód zdecydowanie nie jest spowodowany catalog_controller_product_delete
wysłaniem zdarzenia, ponieważ ten sam kod można znaleźć w kilku miejscach (sprawdź massDelete
metody) w rdzeniu Magento. Użyłem przykładu produktów do podkreślenia wydajności, ponieważ zwykle są to największe podmioty
delete()
wykonuje zapytanie DELETE zamiast ładowania kolekcji i usuwania każdego produktu. Dzięki temu naprawdę przegrasz wydarzenia.
getSingleton()
jako miary wydajności, zamiast oczywistego użycia kolekcji. Aha, możliwe jest również wywołanie zdarzenia za pomocą kolekcji, ale nie za pomocąwalk()
skrótu.