अनुवादक का ध्यान दें: मैंने यह भी सोचा था कि लेखों का समय "क्या तेज है - दोहरा या एकल उद्धरण?" इसे 10 साल पहले एक और समय लगा। लेकिन यहां एक समान लेख ("क्या प्रदर्शन चालें वास्तव में काम करती हैं") हाल ही में रेडिट पर एक अपेक्षाकृत उच्च रेटिंग एकत्र की और यहां तक कि हैबे पर PHP डाइजेस्ट में मिला। तदनुसार, मैंने इन और समान परीक्षणों के महत्वपूर्ण विश्लेषण के साथ लेख का अनुवाद करने का निर्णय लिया।
कई लेख (और यहां तक कि पूरी साइटें) विभिन्न सिंटैक्टिक निर्माणों के प्रदर्शन की तुलना करने और इस आधार पर बताते हुए विभिन्न परीक्षणों को लॉन्च करने के लिए समर्पित हैं कि एक दूसरे की तुलना में तेज है।
मुख्य समस्या है
इस तरह के परीक्षण कई कारणों से गलत हैं, जिसमें सवाल पूछने से लेकर कार्यान्वयन में त्रुटियां हैं। लेकिन सबसे महत्वपूर्ण बात - ऐसे परीक्षण अर्थहीन हैं और एक ही समय में हानिकारक हैं।
- वे व्यर्थ हैं क्योंकि वे कोई व्यावहारिक मूल्य नहीं रखते हैं। इस तरह के लेखों में प्रदान किए गए तरीकों का उपयोग करके किसी भी वास्तविक परियोजना को कभी गति नहीं दी गई है। सिर्फ इसलिए कि प्रदर्शन के लिए वाक्य रचना में अंतर नहीं है, लेकिन डेटा प्रोसेसिंग।
- वे हानिकारक हैं क्योंकि वे बेतहाशा अंधविश्वासों की उपस्थिति का नेतृत्व करते हैं और - इससे भी बदतर - खराब कोड लिखने के लिए पाठकों को प्रोत्साहित करते हैं, यह सोचकर कि वे इसे "अनुकूलित" करते हैं।
यह प्रश्न बंद करने के लिए पर्याप्त होना चाहिए। लेकिन भले ही आप खेल के नियमों को स्वीकार करते हैं और यह दिखाते हैं कि इन "परीक्षणों" में कम से कम कुछ अर्थ है, यह पता चलता है कि उनके परिणाम केवल परीक्षक के ज्ञान की कमी और किसी भी अनुभव की कमी को प्रदर्शित करने के लिए कम किए जाते हैं।
सिंगल बनाम डबल
कुख्यात उद्धरण लें, "एकल बनाम डबल"। बेशक, कोई उद्धरण तेज नहीं है। सबसे पहले, ओपोड कैश के रूप में एक ऐसी चीज है, जो कैश में PHP स्क्रिप्ट को पार्स करने का परिणाम संग्रहीत करती है। इस स्थिति में, PHP कोड को opcode प्रारूप में सहेजा जाता है, जहाँ समान स्ट्रिंग शाब्दिक को बिल्कुल समान संस्थाओं के रूप में संग्रहीत किया जाता है, भले ही PHP स्क्रिप्ट में उद्धरण का उपयोग किया गया हो। जिसका अर्थ है प्रदर्शन में भी सैद्धांतिक अंतर का अभाव।
लेकिन भले ही हम opcode कैश का उपयोग नहीं करते हैं (हालांकि हमें चाहिए, यदि हमारा कार्य वास्तव में प्रदर्शन को बढ़ाना है), तो हम पाएंगे कि पार्सिंग कोड में अंतर इतना छोटा है (एकल-बाइट वर्णों की तुलना में कई सशर्त संक्रमण, शाब्दिक रूप से कई प्रोसेसर निर्देश हैं कि यह बिल्कुल होगा undetectable। इसका मतलब यह है कि प्राप्त किए गए कोई भी परिणाम परीक्षण वातावरण में केवल समस्याओं को प्रदर्शित करेंगे। PHP के कोर डेवलपर निकिता पोपोव के सिंगल कोट्स परफॉरमेंस मिथ को डिसप्रूव करते हुए एक बहुत विस्तृत लेख है, जो इस मुद्दे को विस्तार से बताता है। फिर भी, समाज में एक ऊर्जावान परीक्षक लगभग हर महीने प्रकट होता है, जो प्रदर्शन में एक काल्पनिक "अंतर" को प्रकट करता है।
तार्किक विसंगतियां
कुछ परीक्षण आम तौर पर अर्थहीन होते हैं, बस प्रश्न प्रस्तुत करने के दृष्टिकोण से: उदाहरण के लिए, "वास्तव में सुपर-महंगा ऑपरेशन फेंक दिया जाता है?" यह अनिवार्य रूप से सवाल है "क्या यह वास्तव में है कि प्रसंस्करण में त्रुटि प्रसंस्करण नहीं की तुलना में अधिक महंगा होगा?"। क्या आप गंभीर हैं? बेशक, कोड में कुछ बुनियादी कार्यक्षमता जोड़ने से यह "धीमा" हो जाएगा। लेकिन इसका मतलब यह नहीं है कि इस तरह के हास्यास्पद बहाने के तहत नई कार्यक्षमता को जोड़ने की आवश्यकता नहीं है। यदि आप इस तरह की बात करते हैं, तो सबसे तेज़ कार्यक्रम वह है जो कुछ भी नहीं करता है! कार्यक्रम उपयोगी होना चाहिए और पहली जगह में त्रुटियों के बिना काम करना चाहिए। और इसके बाद ही इसे प्राप्त किया जाता है, और केवल अगर यह धीरे-धीरे काम करता है, तो इसे अनुकूलित करने की आवश्यकता है। लेकिन अगर सवाल ही समझ में नहीं आता है, तो परीक्षण प्रदर्शन को परेशान क्यों करें? यह हास्यास्पद है कि परीक्षक इस संवेदनहीन परीक्षण को भी सही ढंग से लागू नहीं कर पाया, जिसे अगले भाग में दिखाया जाएगा।
या एक अन्य उदाहरण, " $row[id]
नामक एक परीक्षण वास्तव में $row['id']
की तुलना में धीमा होगा?" यह अनिवार्य रूप से सवाल है "कौन सा कोड तेज है - वह जो त्रुटियों के साथ काम करता है, या बिना?" (चूंकि इस मामले में उद्धरण के बिना id
लिखना E_NOTICE
स्तर की एक त्रुटि है, और इस तरह के लेखन को PHP के भविष्य के संस्करणों में पदावनत किया जाएगा)। WTF? आम तौर पर त्रुटि कोड के प्रदर्शन को मापने का क्या मतलब है? त्रुटि को केवल इसलिए ठीक किया जाना चाहिए क्योंकि यह एक त्रुटि है, और इसलिए नहीं कि यह कोड को धीमा कर देगा। यह हास्यास्पद है कि परीक्षक इस संवेदनहीन परीक्षण को भी सही ढंग से लागू नहीं कर पाया, जिसे अगले भाग में दिखाया जाएगा।
परीक्षण की गुणवत्ता
और फिर से - यहां तक कि एक जानबूझकर बेकार परीक्षण सुसंगत, सुसंगत होना चाहिए - अर्थात्, तुलनीय मूल्यों को मापें। लेकिन, एक नियम के रूप में, इस तरह के परीक्षण बाईं एड़ी के साथ किए जाते हैं, और परिणामस्वरूप, प्राप्त परिणाम अर्थहीन होते हैं और कार्य के लिए प्रासंगिक नहीं होते हैं।
उदाहरण के लिए, हमारे बेवकूफ परीक्षक ने " try..catch
ऑपरेटर के अत्यधिक उपयोग" को मापने का काम किया। लेकिन वर्तमान परीक्षण में, उन्होंने न केवल try catch
मापन किया, बल्कि लूप के प्रत्येक पुनरावृत्ति पर एक अपवाद फेंकते हुए throw
भी throw
। लेकिन इस तरह की परीक्षा केवल गलत है, क्योंकि वास्तविक जीवन में त्रुटियां प्रत्येक स्क्रिप्ट निष्पादन के साथ नहीं होती हैं।
बेशक, परीक्षण PHP के बीटा संस्करणों पर नहीं किए जाने चाहिए और प्रयोगात्मक लोगों के साथ मुख्यधारा के समाधान की तुलना नहीं करनी चाहिए। और अगर परीक्षक "जोंस और एक्सएमएल की पार्सिंग गति" की तुलना करने का उपक्रम करता है, तो उसे परीक्षणों में प्रयोगात्मक फ़ंक्शन का उपयोग नहीं करना चाहिए।
कुछ परीक्षण बस उसके द्वारा निर्धारित कार्य के परीक्षक द्वारा पूरी गलतफहमी को प्रदर्शित करते हैं। हाल ही में प्रकाशित लेख से एक समान उदाहरण पहले ही ऊपर उल्लेख किया गया था: परीक्षण के लेखक ने यह पता लगाने की कोशिश की कि क्या त्रुटि के कारण कोड ("अपरिभाषित स्थिर का उपयोग") त्रुटियों के बिना कोड की तुलना में धीमा होगा (जो एक वाक्यविन्यास सही स्ट्रिंग शाब्दिक का उपयोग करता है), लेकिन विफल रहा यहां तक कि इस स्पष्ट रूप से अर्थहीन परीक्षण के साथ, बिना उद्धृत संख्या के प्रदर्शन के साथ एक उद्धृत संख्या के प्रदर्शन की तुलना करना। बेशक, आप PHP (स्ट्रिंग्स के विपरीत) में उद्धरण के बिना संख्या लिख सकते हैं, और परिणामस्वरूप, लेखक ने गलत परिणाम प्राप्त करते हुए एक पूरी तरह से अलग कार्यक्षमता का परीक्षण किया।
विचार करने के लिए अन्य मुद्दे हैं, जैसे कि परीक्षण वातावरण। PHP में एक्सडबग जैसे एक्सटेंशन हैं जो परीक्षा परिणामों पर बहुत बड़ा प्रभाव डाल सकते हैं। या पहले से ही उल्लेखित ओपेक कैश, जिसे प्रदर्शन परीक्षणों के दौरान शामिल किया जाना चाहिए ताकि परीक्षण के परिणाम कम से कम कुछ समझ सकें।
परीक्षण कैसे किया जाता है यह भी मायने रखता है। चूंकि PHP प्रक्रिया प्रत्येक अनुरोध के बाद पूरी तरह से मर जाती है, इसलिए यह पूरे जीवन चक्र के प्रदर्शन का परीक्षण करने के लिए समझ में आता है, एक वेब सर्वर से कनेक्शन बनाने से शुरू होकर इस कनेक्शन को बंद करने तक। अपाचे बेंचमार्क या घेराबंदी जैसी उपयोगिताओं हैं जो आपको ऐसा करने देती हैं।
वास्तविक प्रदर्शन में सुधार
यह सब अच्छा है, लेकिन पाठक को इस लेख से क्या निष्कर्ष निकालना चाहिए? परिभाषा के अनुसार कौन से प्रदर्शन परीक्षण बेकार हैं? बिल्कुल नहीं। लेकिन क्या वास्तव में मायने रखता है यही कारण है कि उन्हें शुरू करना चाहिए। खरोंच से परीक्षण समय की बर्बादी है। हमेशा प्रदर्शन परीक्षण चलाने का एक विशिष्ट कारण होना चाहिए। और इस कारण को "प्रोफाइलिंग" कहा जाता है। जब आपका आवेदन धीरे-धीरे चलना शुरू होता है, तो आपको प्रोफाइलिंग करने की आवश्यकता होती है, जिसका अर्थ है कि सबसे धीमी गति को खोजने के लिए कोड के विभिन्न वर्गों की गति को मापना। ऐसी साइट पाए जाने के बाद, हमें इसका कारण निर्धारित करना चाहिए। अधिकतर, यह या तो आवश्यकता से अधिक बड़ा होता है, संसाधित डेटा की मात्रा, या बाहरी डेटा स्रोत के लिए अनुरोध। पहले मामले के लिए, ऑप्टिमाइज़ेशन में संसाधित डेटा की मात्रा को कम करने, और दूसरे मामले के लिए, क्वेरी परिणामों को कैशिंग किया जाएगा।
उदाहरण के लिए, प्रदर्शन के संदर्भ में, इससे कोई फर्क नहीं पड़ता कि हम स्पष्ट रूप से निर्धारित लूप का उपयोग करते हैं या अंतर्निहित फ़ंक्शन को संसाधित करने के लिए अंतर्निहित PHP फ़ंक्शन का उपयोग करते हैं (जो अनिवार्य रूप से सिंटैक्टिक चीनी है)। वास्तव में जो महत्वपूर्ण है वह उस डेटा की मात्रा है जिसे हम प्रसंस्करण के लिए संचारित करते हैं। यदि यह अनुचित रूप से बड़ा है, तो हमें इसे ट्रिम करना होगा, या प्रोसेसिंग को कहीं और (डेटाबेस में) स्थानांतरित करना होगा। यह हमें एक विशाल प्रदर्शन को बढ़ावा देगा जो वास्तविक होगा। जबकि डेटा प्रोसेसिंग के लिए लूप को कॉल करने के तरीकों के बीच का अंतर बिल्कुल ध्यान देने योग्य नहीं है।
ऐसे अनिवार्य प्रदर्शन सुधार करने के बाद ही, या यदि हम संसाधित डेटा की मात्रा में कटौती नहीं कर सकते हैं, तो क्या हम प्रदर्शन परीक्षण शुरू कर सकते हैं। लेकिन फिर, ऐसे परीक्षण खरोंच से नहीं किए जाने चाहिए। स्पष्ट लूप और इनलाइन फ़ंक्शन के प्रदर्शन की तुलना शुरू करने के लिए, हमें यह सुनिश्चित करना चाहिए कि लूप समस्या का कारण है, न कि इसकी सामग्री (बिगाड़ने वाला: बेशक, यह सामग्री है)।
मेरे अभ्यास से एक हालिया उदाहरण: कोड में डॉक्ट्रिन क्वेरी बिल्डर का उपयोग करते हुए एक क्वेरी थी, जिसे कई हजार मापदंडों को लेना था। क्वेरी अपने आप में काफी तेज़ है, लेकिन कई हजार मापदंडों को पचाने में डॉक्ट्रिन को काफी समय लगता है। नतीजतन, क्वेरी को शुद्ध एसक्यूएल में फिर से लिखा गया था, और मापदंडों को पीडीओ लाइब्रेरी के निष्पादन () विधि में स्थानांतरित कर दिया गया था, जो कि लगभग तुरंत ही इतने सारे मापदंडों के साथ मुकाबला करता है।
क्या इसका मतलब यह है कि मैं कभी डॉक्ट्रिन क्वेरी बिल्डर का उपयोग नहीं करूंगा? बिल्कुल नहीं। यह 99% कार्यों के लिए एकदम सही है, और मैं इसे सभी प्रश्नों के लिए उपयोग करना जारी रखूंगा। और केवल असाधारण मामलों में यह कम सुविधाजनक, लेकिन अधिक उत्पादक विधि का उपयोग करने के लायक है।
इस चयन के लिए क्वेरी और मापदंडों का निर्माण एक लूप में किया गया था। यदि मेरे पास चक्र को कैसे कहा जाता है, तो इससे निपटने के लिए एक बेवकूफ विचार था, तो मैं बस बिना किसी सकारात्मक परिणाम के समय खो दूंगा। और यह सभी प्रदर्शन अनुकूलन का बहुत सार है: केवल उस कोड को अनुकूलित करने के लिए जो आपके विशेष मामले में धीरे-धीरे चलता है । और वह कोड नहीं जिसे बहुत पहले धीमा माना जाता था, एक दूर की, दूर की आकाशगंगा में, या उस कोड को जो किसी को अर्थहीन परीक्षणों के आधार पर धीमी गति से कॉल करने के लिए हुआ था।