Magento 1: संस्थाओं को हटाने के लिए प्रदर्शन अनुकूलन


10

मैं वर्तमान में प्रदर्शन के बारे में कुछ मॉड्यूल सुधारने की कोशिश कर रहा हूं।

आप में से कुछ लोग संग्रह पर विधि के उपयोग को जान सकते हैं जो सीधे उत्पादों के माध्यम से लूपिंग से बचने के लिए बहुत उपयोगी है।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.84MB का उपयोग किया गया
  • कस्टम कोड: 17.12 सेकंड, 15.45MB उपयोग किया जाता है

तो 100 उत्पादों को हटाने के लिए, मेरा कस्टम कोड 3 सेकंड तेज है और 0.4MB कम उपयोग करता है।

टेस्ट 2: संग्रह delete()विधि का उपयोग करना

मैंने इस एक के साथ मूल कोड को बदल दिया:

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

और मन यहाँ उड़ा परिणाम हैं:

  • मूल कोड: 19.97 सेकंड, 15.84MB का उपयोग किया गया
  • कस्टम कोड: 1.24 सेकंड, 6.34MB का उपयोग किया

तो 100 उत्पादों को हटाने के लिए, मेरा कस्टम कोड 18 सेकंड तेज है और 9MB कम उपयोग करता है।

जैसा कि टिप्पणियों में कहा गया है, ऐसा लगता है कि यह विधि Magento की घटनाओं (लोड के बाद, हटाने के बाद) और न ही सूचकांक / कैश फ्लश को ट्रिगर नहीं करती है।

सवाल

तो मेरा सवाल यह है: क्या कोई कारण है कि मैगेंटो कोर टीम ने लूप में उत्पादों को लोड करने के बजाय walk('delete')संग्रह delete()विधि का बेहतर उपयोग नहीं किया (जिसे हम सभी जानते हैं कि यह बहुत बुरा अभ्यास है)?

मुख्य लक्ष्य मॉड्यूल विकास के मामले में ऐसे प्रमुख बिंदुओं से अवगत होना है: क्या कोई विशेष मामले हैं जहां कोई walk/ संग्रह delete()विधि का उपयोग नहीं कर सकता है ?

संपादित करें: कारण निश्चित रूप से नहीं है क्योंकि catalog_controller_product_deleteईवेंट को भेजा जा रहा है क्योंकि massDeleteमैगेंटो कोर में कई स्थानों पर एक ही कोड पाया जा सकता है ( विधियों की जांच करें )। मैंने प्रदर्शन को उजागर करने के लिए उत्पादों के उदाहरण का उपयोग किया है क्योंकि वे आमतौर पर सबसे बड़ी संस्थाएं हैं


3
मुझे लगता है कि यह घटना के कारण है। लेकिन मैं आपसे सहमत हूं, यह खराब शैली है, विशेष getSingleton()रूप से प्रदर्शन संग्रह के रूप में उपयोग, स्पष्ट संग्रह उपयोग के बजाय। ओह, और एक संग्रह के साथ घटना को ट्रिगर करना संभव है, बस walk()शॉर्टकट के साथ नहीं ।
फाबियन शेंगलर

1
@fschmengler हाँ, मैंने इस घटना के बारे में भी सोचा था लेकिन जैसा कि मैंने अपने संपादन में कहा, यह बहुत सारी जगहों पर हो रहा है जहाँ कोई भी घटना नहीं हो रही है।
राफेल में डिजिटल पियानोवाद

3
आश्चर्य की बात नहीं। delete()संग्रह को लोड करने और प्रत्येक उत्पाद को हटाने के बजाय DELETE क्वेरी बनाता है। उस एक के साथ आप वास्तव में घटनाओं को ढीला करेंगे।
फेबियन शेंगलर

5
@fschmengler एक संग्रह डिलीट प्रत्येक व्यक्तिगत आइटम के लिए एक डिलीट भी करता है, लेकिन यह कैश को साफ़ करता है और कुछ मैगनेटो और इंडेक्सर घटनाओं को ट्रिगर करता है। बस यहीं से अंतर आना चाहिए।
विनय

2
@Vinai तुम सही हो। मेरी तरफ से इच्छाधारी सोच
Fabian Schmengler

जवाबों:


4

इसलिए मैंने कुछ प्रदर्शन परीक्षण किए, 100 उत्पादों को हटाने के लिए समय और मेमोरी उपयोग की जांच के लिए कुछ लॉगिंग कॉल जोड़े

साइड नोट, लेकिन आपको इसके लिए वैरिएन प्रोफाइलर का उपयोग करना चाहिए!

मेरा कस्टम कोड 2 सेकंड्स तेज है और 0.4MB कम उपयोग करता है

हालांकि मुझे संदेह नहीं है कि आपके परिवर्तन से प्रदर्शन में सुधार होगा, यह सुधारों की तुलना करने के लिए "पहले" परिणाम प्रदान करने के लिए उपयोगी होगा।

क्या कोई कारण है कि मैगेंटो कोर टीम ने walk('delete')लूप में लोडिंग उत्पादों के बजाय इसका उपयोग नहीं किया (जो हम सभी जानते हैं कि यह बहुत महत्वपूर्ण अभ्यास है)?

ठीक है, हम इस मंच पर अन्य सवालों से जानते हैं:

  • Magento कोडबेस कई वर्षों में विकसित और विकसित हुआ है
  • इस पर बहुत सारे डेवलपर्स काम कर रहे थे
  • Magento के कोर डेवलपमेंट वर्कफ़्लो प्रक्रियाओं ने समय के साथ प्लेटफ़ॉर्म पर काम करने में नाटकीय रूप से सुधार किया है, आधुनिक सर्वोत्तम प्रथाओं और तकनीकों के साथ उस बिंदु पर पकड़ रहा है जहां Magento 2 अब कई अग्रणी आधुनिक एप्लिकेशन डिज़ाइन प्रथाओं का प्रदर्शन करता है

इसलिए मैं सुझाव दूंगा कि आपके द्वारा पाया गया उदाहरण संभवतः कोड में छिपे कई संभावित रत्नों में से एक है, जो या तो बहुत पहले लिखे गए थे, और / या कम अनुभवी डेवलपर द्वारा। मुख्य कोड की तरह (और सामुदायिक कोड!) यह एक छोटे से डेटा सेट पर परीक्षण किया गया होगा और लड़ाई का परीक्षण नहीं किया गया था, इसलिए प्रदर्शन की बारीकी से निगरानी नहीं की जा सकती है।

क्या मूल कोड की तुलना में आपका अभ्यास फायदेमंद है, और सबसे अच्छा अभ्यास करने के लिए अधिक बारीकी से गठबंधन किया गया है? हाँ। आप एक समुदाय के रूप में Magento [1.x] डेवलपर के पास हालांकि सुझाए गए सुधारों में योगदान करने की कोई क्षमता नहीं है, जैसे कि आप Magento 2 के साथ करते हैं, इसलिए मेरा सुझाव यह है कि आप इसे अपने किसी एक स्टोर में प्रदर्शन के लिए आवश्यक होने पर स्थानीय मॉड्यूल में लागू करें। , या इसे अनदेखा करें यदि यह आपको प्रभावित नहीं कर रहा है लेकिन आपने कुछ शोध करते समय इस पर ध्यान दिया है।

अपने प्रश्न को संपादित करने के अपडेट के रूप में, मुझे यकीन है कि आप जानते हैं कि वारीन_डाटा_कोलक्शन में चलने की विधि एक मनमाना कॉलबैक स्वीकार करती है, इसलिए आप इसे किसी भी चीज़ के लिए उपयोग करने के लिए स्वतंत्र होंगे जो आप शायद चाहते थे। ईवेंट को मूल उदाहरण में भेजने के लिए आप वॉक फंक्शन के साथ-साथ डिलीट भी कर सकते हैं।

एकमात्र कारण जिसकी मैं कल्पना कर सकता हूं कि हटाने से पहले उत्पाद को लोड करना उपयोग का होगा, हो सकता है कि उस घटना से जुड़े पर्यवेक्षकों को पहले उत्पाद को लोड किए बिना पूर्ण डेटा सेट की आवश्यकता न हो। यदि ऐसा है, तो यह समझाता है कि वे वस्तु के ओवरहेड्स को कम से कम करने के लिए एक मॉडल के बजाय एक सिंगलटन का उपयोग क्यों करते हैं।


धन्यवाद मैंने पोस्ट के परिणामों के पहले और बाद में जोड़ा है। तो आपको लगता है कि इस पुराने कोड के अलावा कोई विशेष कारण नहीं है?
राफेल डिजिटल पियानोवाद

2
यह मेरा अनुमान होगा, हाँ। हटाने से पहले उत्पाद को लोड करने से पहले लोड घटनाओं को हटाने के अलावा कोई लाभ नहीं होगा, जो हटाने के लिए प्रासंगिक नहीं है। आम तौर पर आप अपने पूर्ण डेटा सेट को प्राप्त करने के लिए एक उत्पाद को लोड करते हैं, जो घटना से जुड़े पर्यवेक्षकों में से एक के लिए आवश्यक हो सकता है - अगर ऐसा है तो यह बताएगा कि वे मॉडल के बजाय एक सिंगलटन का उपयोग क्यों कर रहे हैं।
रॉबी एवेरिल

1
अधिक परीक्षणों के साथ मेरे संपादन को देखें, परिणाम और भी
अजीब हैं

0

मेरी सोच यह है कि वे इसे उस catalog_controller_product_deleteघटना को आग लगाने के लिए कर रहे हैं जिसका उपयोग Mage_Tag द्वारा किया जा रहा है।

catalog_product_delete_beforeया catalog_product_delete_afterइसका मतलब यह होगा कि मैं अनावश्यक था, लेकिन मुझे लगता है कि होगा। आश्चर्य है कि इस विशेष घटना का उपयोग व्यवस्थापक कार्रवाई लॉगिंग के लिए भी किया जाता है।


इसके बारे में भी सोचा, लेकिन यह निश्चित रूप से नहीं है क्योंकि यह भी massDelete()कार्रवाई के लिए होता हैCustomerController.php
राफेल पर डिजिटल पियानोवाद

अधिक परीक्षणों के साथ मेरे संपादन को देखें, परिणाम और भी
अजीब हैं

0

मुझे लगता है कि मास-डिलीट को सिंगल (पूरी तरह से लोड) उत्पाद को हटाने जैसा काम करना चाहिए।

के लिए $collection->delete()जवाब पहले से ही दिया जाता है। यदि आप ट्रिगर नहीं करते हैं deleter_before, तो delete_afterमैं संभवतः कुछ एक्सटेंशन तोड़ सकता हूं और कोर में उपयोग किए गए कुछ पर्यवेक्षकों को बायपास करूंगा।

$collection->walk('delete')संभवतः काम करेगा, लेकिन अभी भी नुकसान है कि उत्पाद डेटा पूर्ण नहीं है। यह कस्टम पर्यवेक्षकों को भी तोड़ सकता है यदि वे अतिरिक्त डेटा पर भरोसा करते हैं, उदाहरण के लिए स्टॉक आइटम ऑब्जेक्ट।

मुझे लगता है, अगर आप इसे बदलते ->addAttributeToSelect('entity_id')हैं ->addAttributeToSelect('*')और ->setFlag('require_stock_items', true)(उत्पादों में स्टॉक डेटा जोड़ने के लिए) यह बेहतर प्रदर्शन नहीं करेगा तो "लूप-डिलीट"।

बुरी शैली की तरह दिखता है, लेकिन मुझे लगता है कि यह दोनों बड़े पैमाने पर हटाने की कार्रवाई के लिए सही है।

मैं कस्टम मॉडल का भी उपयोग करता हूं walk()और करता हूं delete(), लेकिन मुझे पता है कि कोई पर्यवेक्षक नहीं है या entity_idपर्याप्त नहीं है। बस उल्लेख करने के लिए, walk()कोर में उपयोग किए जाने वाले सभी घटनाओं के साथ काम करेंगे, क्योंकि वे केवल उपयोग करते हैं $product->getId(), लेकिन आप तृतीय-पक्ष पर्यवेक्षकों के बारे में नहीं जानते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.