Saat ini saya mencoba untuk meningkatkan beberapa modul mengenai kinerja.
Beberapa dari Anda mungkin tahu penggunaan walk()
metode pengumpulan yang sangat berguna untuk menghindari perulangan melalui produk secara langsung.
Selain itu dan terima kasih kepada @Vinai, Anda juga dapat menggunakan delete()
metode pengumpulan .
Tapi saya perhatikan bahwa file asli Magento 1 tidak selalu menggunakan metode apa pun untuk dihapus.
Salah satu kode terburuk yang pernah saya lihat adalah massDelete()
metode dari app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php
mana produk dimuat dalam satu lingkaran sebelum dihapus .
foreach ($productIds as $productId) {
$product = Mage::getSingleton('catalog/product')->load($productId);
Mage::dispatchEvent('catalog_controller_product_delete', array('product' => $product));
$product->delete();
}
Jadi saya melakukan beberapa tes kinerja, menambahkan beberapa panggilan logging untuk memeriksa waktu yang dibutuhkan dan penggunaan memori untuk 100 penghapusan produk.
Tes 1: walk
metode
Saya mengganti kode asli yang disisipkan di atas dengan kode ini:
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('entity_id')
->addIdFilter($productIds)
->walk('delete');
Dan hasil saya adalah sebagai berikut pada server dev jelek saya (rata-rata berdasarkan 10 tes):
- Kode asli: 19,97 detik, 15,84 MB digunakan
- Kode khusus: 17.12 detik, 15.45MB digunakan
Jadi untuk penghapusan 100 produk, kode khusus saya adalah 3 detik lebih cepat dan menggunakan 0.4MB lebih sedikit.
Tes 2: Menggunakan delete()
metode pengumpulan
Saya mengganti kode asli dengan yang ini:
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('entity_id')
->addIdFilter($productIds)
->delete();
Dan mind blown di sini adalah hasilnya:
- Kode asli: 19,97 detik, 15,84 MB digunakan
- Kode khusus: 1,24 detik, 6,34MB digunakan
Jadi untuk penghapusan 100 produk, kode khusus saya adalah 18 detik lebih cepat dan menggunakan 9MB lebih sedikit.
Seperti yang dinyatakan dalam komentar, sepertinya metode ini tidak memicu peristiwa Magento (setelah memuat, setelah menghapus) atau indeks / cache flush.
Pertanyaan
Jadi pertanyaan saya adalah: adakah alasan mengapa tim inti Magento tidak menggunakan walk('delete')
atau bahkan lebih baik menggunakan delete()
metode pengumpulan daripada memuat produk dalam satu lingkaran (yang kita semua tahu adalah praktik yang sangat sangat buruk)?
Tujuan utamanya adalah untuk mengetahui poin-poin penting tersebut dalam kasus pengembangan modul: apakah ada kasus tertentu di mana seseorang tidak dapat menggunakan metode walk
/ collection delete()
?
SUNTING: alasannya jelas bukan karena catalog_controller_product_delete
peristiwa yang dikirim karena kode yang sama dapat ditemukan di beberapa tempat (periksa massDelete
metode) di inti Magento. Saya telah menggunakan contoh produk untuk menyoroti kinerja karena biasanya merupakan entitas terbesar
sumber
getSingleton()
sebagai ukuran kinerja, bukan penggunaan koleksi yang jelas. Oh dan itu mungkin untuk memicu acara dengan koleksi juga, hanya saja tidak dengan jalanwalk()
pintas.delete()
membuat kueri HAPUS alih-alih memuat koleksi dan menghapus setiap produk. Dengan itu Anda akan benar-benar kehilangan acara.Jawaban:
Catatan, tetapi Anda harus melihat menggunakan Varien Profiler untuk ini!
Meskipun saya tidak ragu bahwa perubahan Anda akan meningkatkan kinerja, akan berguna untuk memberikan hasil "sebelum" untuk membandingkan peningkatan.
Nah, kita tahu dari pertanyaan lain di forum ini sebagai berikut:
Jadi saya akan menyarankan bahwa contoh yang Anda temukan mungkin adalah salah satu dari banyak permata yang berpotensi tersembunyi dalam kode yang telah ditulis sebelumnya, dan / atau oleh pengembang yang kurang berpengalaman. Seperti banyak kode inti (dan kode komunitas!) Itu akan diuji pada kumpulan data kecil dan tidak diuji pertempuran, sehingga kinerja mungkin tidak dipantau secara ketat.
Apakah peningkatan Anda bermanfaat, dan lebih selaras dengan praktik terbaik daripada kode asli? Iya. Anda sebagai pengembang Magento [1.x] komunitas namun tidak memiliki kemampuan untuk berkontribusi perbaikan yang disarankan meskipun seperti yang Anda lakukan dengan Magento 2, jadi saran saya akan menerapkan ini dalam modul lokal jika Anda memerlukannya untuk kinerja di salah satu toko Anda , atau abaikan saja jika itu tidak memengaruhi Anda tetapi Anda menyadarinya saat melakukan riset.
Sebagai pembaruan pada edit pertanyaan Anda, saya yakin Anda mengetahui bahwa metode jalan di Varien_Data_Collection menerima panggilan balik sewenang-wenang, jadi Anda akan bebas menggunakannya untuk apa pun yang Anda inginkan. Untuk mengirim acara dalam contoh asli Anda bisa melakukannya dengan fungsi jalan kaki, serta menghapus.
Satu-satunya alasan saya bisa membayangkan bahwa memuat produk sebelum menghapusnya akan berguna mungkin karena pengamat yang melekat pada acara itu mungkin memerlukan set data lengkap tidak tersedia tanpa memuat produk terlebih dahulu. Jika itu masalahnya, itu akan menjelaskan mengapa mereka menggunakan singleton daripada model untuk setidaknya meminimalkan overhead objek.
sumber
catalog_controller_product_delete
Pemikir saya adalah mereka melakukannya untuk memecat acara yang sedang digunakan oleh Mage_Tag.catalog_product_delete_before
ataucatalog_product_delete_after
akan berarti ini tidak perlu meskipun saya akan berpikir. Bertanya-tanya apakah acara khusus ini juga digunakan untuk pencatatan tindakan Admin.sumber
massDelete()
aksiCustomerController.php
Saya pikir penghapusan massal harus berfungsi seperti menghapus satu produk (terisi penuh).
Untuk
$collection->delete()
jawabannya sudah diberikan. Jika Anda tidak memicudeleter_before
,delete_after
saya mungkin dapat merusak beberapa ekstensi dan akan memotong beberapa pengamat yang digunakan dalam inti.$collection->walk('delete')
mungkin bekerja, tetapi masih memiliki kelemahan bahwa data produk tidak lengkap. Ini juga dapat merusak pengamat khusus jika mereka bergantung pada data tambahan, misalnya objek item persediaan.Saya kira, jika Anda mengubah
->addAttributeToSelect('entity_id')
ke->addAttributeToSelect('*')
dan add->setFlag('require_stock_items', true)
(untuk menambahkan data stok produk) tidak akan melakukan lebih baik maka "loop-delete".Sepertinya gaya yang buruk, tapi saya pikir itu tepat untuk kedua tindakan penghapusan massal.
Saya menggunakan
walk()
dandelete()
untuk model khusus juga, tetapi saya tahu bahwa tidak ada pengamat atauentity_id
cukup. Hanya untuk menyebutkan,walk()
akan bekerja dengan semua acara yang digunakan dalam inti, karena hanya digunakan$product->getId()
, tetapi Anda tidak tahu tentang pengamat pihak ke-3.sumber