Magento 1: Varlıkları silmek için performans optimizasyonları


10

Şu anda performansla ilgili birkaç modülü geliştirmeye çalışıyorum.

Bazılarınız, doğrudan ürünlerin arasında dolaşmayı önlemek için çok yararlı olan toplama yönteminin kullanımını biliyor olabilirsiniz .walk()

Bunun üzerine ve @Vinai sayesinde , toplama delete()yöntemi de kullanılabilir .

Ancak Magento 1 yerel dosyalarının her zaman silmek için bu yöntemlerden hiçbirini kullanmadığını fark ettim.

Gördüğüm en kötü kod biri massDelete()itibaren yöntem app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.phpnerede ürünler silmeden önce bir döngü içinde yüklenir .

foreach ($productIds as $productId) {
    $product = Mage::getSingleton('catalog/product')->load($productId);
    Mage::dispatchEvent('catalog_controller_product_delete', array('product' => $product));
    $product->delete();
}

Bu yüzden bazı performans testleri yaptım, geçen süreyi ve 100 ürünün silinmesi için bellek kullanımını kontrol etmek için bazı günlük çağrıları ekledim.

Test 1: walkyöntem

Yukarıda yapıştırılan orijinal kodu bu kodla değiştirdim:

$collection = Mage::getResourceModel('catalog/product_collection')
                        ->addAttributeToSelect('entity_id')
                        ->addIdFilter($productIds)
                        ->walk('delete');

Ve sonuçlarım crappy dev sunucumda şu şekildedir (ortalama 10 teste dayanmaktadır):

  • Orijinal kod: 19.97 saniye, 15.84MB kullanılmış
  • Özel kod: 17.12 saniye, 15.45MB kullanılmış

100 ürün silme için özel kodum 3 saniye daha hızlı ve 0,4MB daha az kullanıyor.

Test 2: Toplama delete()yöntemini kullanma

Orijinal kodunu bununla değiştirdim:

$collection = Mage::getResourceModel('catalog/product_collection')
                        ->addAttributeToSelect('entity_id')
                        ->addIdFilter($productIds)
                        ->delete();

Ve burada üflenen zihin sonuçları:

  • Orijinal kod: 19.97 saniye, 15.84MB kullanılmış
  • Özel kod: 1.24 saniye, 6.34MB kullanılmış

Bu yüzden 100 ürün silme için özel kodum 18 saniye daha hızlı ve 9 MB daha az kullanıyor.

Yorumlarda belirtildiği gibi, bu yöntem Magento olaylarını (yükten sonra, sildikten sonra) veya dizin / önbellek sifonunu tetiklemiyor gibi görünüyor.

Soru

Yani sorum şu: Magento çekirdek ekibinin, ürünleri bir döngüde yüklemek yerine ( walk('delete')ya da delete()çok kötü bir uygulama olduğunu bildiğimiz) toplama yöntemini veya olayı daha iyi kullanmamasının bir nedeni var mı?

Ana amaç, bir modül geliştirme durumunda bu kilit noktaların farkında olmaktır: / collection yöntemini kullanamayan belirli durumlar var mı?walkdelete()

DÜZENLEME: Nedeni kesinlikle Magento çekirdeğinde catalog_controller_product_deletebirkaç yerde aynı massDeleteyöntemleri ( yöntemleri kontrol ) bulunabilir olarak sevk olay nedeniyle değildir . Genellikle en büyük varlıklar oldukları için performansı vurgulamak için ürün örneğini kullandım


3
Sanırım olay yüzünden. Ama sana katılıyorum, bu kötü bir stil, özellikle getSingleton()belirgin toplama kullanımı yerine performans ölçüsü olarak kullanılması. Oh ve olayı bir koleksiyonla da tetiklemek mümkün, sadece walk()kısayol ile değil .
Fabian Schmengler

1
@ fschmengler evet olayı ben de düşündüm ama düzenlememde söylediğim gibi, hiçbir olayın gönderilmediği birçok yerde oluyor.
Raphael, Dijital Piyanizm'de

3
Şaşırtıcı değil. delete()koleksiyonu yüklemek ve her ürünü silmek yerine SİL sorgusu yapar. Bununla gerçekten olayları kaybedeceksiniz.
Fabian Schmengler

5
@fschmengler Koleksiyon silme işlemi her bir öğe için bir silme işlemi gerçekleştirir, ancak önbelleği temizlemeyi ve bazı macenta ve dizin oluşturucu olaylarını tetiklemeyi atlar. Farkın buradan gelmesi gerekiyor.
Vinai

2
@Vinai haklısın. Benim tarafımda
Dilek

Yanıtlar:


4

Bu yüzden bazı performans testleri yaptım, geçen süreyi ve 100 ürünün silinmesi için bellek kullanımını kontrol etmek için bazı günlük çağrıları ekledim

Yan not, ancak bunun için Varien Profiler'ı kullanmaya bakmalısınız!

özel kodum 2 saniye daha hızlı ve 0,4 MB daha az kullanıyor

Değişikliğinizin performansı artıracağından şüphe etmememe rağmen, iyileştirmeleri karşılaştırmak için "önceki" sonuçları sağlamak yararlı olacaktır.

Magento çekirdek ekibinin walk('delete')ürünleri bir döngüde yüklemek yerine (neden hepimiz çok çok kötü bir uygulama olduğunu biliyoruz) kullanmamasının bir nedeni var mı?

Bu forumdaki diğer sorulardan aşağıdakileri biliyoruz:

  • Magento kod tabanı uzun yıllar boyunca gelişti ve gelişti
  • Üzerinde çalışan bir sürü geliştirici vardı
  • Magento çekirdek geliştirme iş akışı süreçleri, platformda çalıştıkları süre boyunca çarpıcı bir şekilde iyileşti ve Magento 2'nin şimdi birçok önde gelen modern uygulama tasarım uygulaması sergilediği noktaya kadar modern en iyi uygulamalar ve teknikler yakaladı

Bu nedenle, bulduğunuz örneğin, kodda uzun zaman önce ve / veya daha az deneyimli bir geliştirici tarafından yazılmış potansiyel olarak çok sayıda mücevherden biri olduğunu öneririm. Çekirdek kodun (ve topluluk kodunun) çoğu gibi, küçük bir veri kümesinde test edilmiş ve savaş testinde değil, bu yüzden performans yakından izlenmemiş olabilir.

İyileştirmeniz faydalı ve orijinal koda göre daha iyi uygulamalarla daha uyumlu mu? Evet. Bir topluluk Magento [1.x] geliştiricisi olarak Magento 2 ile yaptığınız gibi önerilen iyileştirmelere katkıda bulunma yeteneğiniz yok, bu nedenle önerim, mağazalarınızdan birinde performans için gerekliyse bunu yerel bir modülde uygulamak olacaktır. veya sizi etkilemiyorsa, ancak biraz araştırma yaparken fark ettiyseniz, görmezden gelin.

Soru düzenlemenizin bir güncellemesi olarak, Varien_Data_Collection içindeki yürüyüş yönteminin keyfi bir geri çağrıyı kabul ettiğinden emin olabilirsiniz, bu yüzden muhtemelen istediğiniz herhangi bir şey için kullanmakta özgürsünüz. Etkinliği orijinal örnekte göndermek için bunu walk işlevinin yanı sıra delete işleviyle de yapabilirsiniz.

Ürünü silmeden önce yüklemenin yararlı olacağını hayal edebilmemizin tek nedeni, o etkinliğe bağlı gözlemcilerin önce ürünü yüklemeden tam veri setine ihtiyaç duyması olabilir. Eğer durum buysa, en azından nesnenin genel giderlerini en aza indirmek için bir model yerine bir singleton kullandıklarını açıklayacaktır.


Teşekkürler gönderiye önceki ve sonraki sonuçları ekledim. Eski kodun dışında özel bir nedeni olmadığını mı düşünüyorsunuz?
Raphael, Dijital Piyanizm'de

2
Bu benim tahminim olurdu, evet. Ürünü silmeden önce yüklemek, silinmeyle ilgili olmayan yük olaylarını tetiklemekten başka bir fayda sağlamaz. Normalde, etkinliğe bağlı gözlemcilerden biri için gerekli olabilecek tam veri kümesini elde etmek için bir ürün yüklersiniz - bu durumda neden model yerine tek birton kullandıklarını açıklar.
Robbie Averill

1
Düzenlememi daha fazla testle görün, sonuçlar daha çılgın
Raphael at Digital Pianism

0

Benim düşünceme catalog_controller_product_deletegöre Mage_Tag tarafından kullanılan olayı ateşlemek için yapıyorlar.

catalog_product_delete_beforeya catalog_product_delete_afterda düşünmemize rağmen bunun gereksiz olduğu anlamına gelir. Bu özel etkinliğin Yönetici işlem günlüğü için de kullanılıp kullanılmadığını merak edin.


Bunu da düşündüm ama bu da massDelete()eylemin gerçekleşmesi için kesinlikle sebep değilCustomerController.php
Raphael at Digital Pianism

Düzenlememi daha fazla testle görün, sonuçlar daha çılgın
Raphael at Digital Pianism

0

Toplu silme, tek (tam yüklü) bir ürünü silmek gibi çalışmalıdır.

İçin $collection->delete()cevap zaten verilir. Tetiklemezseniz deleter_before, delete_aftermuhtemelen bazı uzantıları kırabilirim ve çekirdekte kullanılan bazı gözlemcileri atlayabilirim.

$collection->walk('delete')muhtemelen işe yarayacaktır, ancak yine de ürün verilerinin tam olmaması dezavantajına sahiptir. Bu, özel gözlemcileri, örneğin stok kalemi nesnesi gibi ek verilere dayanmaları durumunda da kırabilir.

Sana değiştirirseniz, tahmin ->addAttributeToSelect('entity_id')etmek ->addAttributeToSelect('*')ve eklemek ->setFlag('require_stock_items', true)daha sonra "loop-delete" daha iyi bir performans göstermez (ürünlere stok veri eklemek için).

Kötü stil gibi görünüyor, ama her iki toplu silme eylemleri için doğru olduğunu düşünüyorum.

Kullandığım walk()ve delete()çok özel modelleri için, ama orada hiçbir gözlemciler ya biliyoruz entity_idyeterlidir. Sadece bahsetmek gerekirse, walk()çekirdekte kullanılan tüm olaylarla çalışırdı, çünkü sadece kullanıyorlar $product->getId(), ancak 3. taraf gözlemcileri bilmiyorsunuz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.