अनुकूलन (वेब) अनुप्रयोगों के लिए दृष्टिकोण

मैं आपके बारे में नहीं जानता, मुझे व्यक्तिगत रूप से कार्यक्रम के प्रदर्शन का अनुकूलन पसंद है। मुझे पसंद है जब प्रोग्राम धीमा नहीं होते हैं, और साइटें जल्दी से खुल जाती हैं। इस लेख में, मैं प्रदर्शन को बेहतर बनाने के लिए कुछ (बुनियादी) दृष्टिकोण देना चाहूंगा। मूल रूप से, वे वेब अनुप्रयोगों से संबंधित हैं, लेकिन "साधारण" कार्यक्रमों के लिए कुछ चीजें सच हैं। मैं प्रोफाइलिंग, बैच प्रोसेसिंग, अनुरोधों के अतुल्यकालिक प्रसंस्करण आदि जैसे विषयों को कवर करूंगा। इस विषय को MySQL का उपयोग करके वेब अनुप्रयोगों को अनुकूलित करने के लिए रणनीतियों का एक निरंतरता माना जा सकता है।

आपको कब अनुकूलन करना चाहिए?


बहुत पहले सवाल जो आपको कुछ अनुकूलन करने से पहले खुद से पूछने की ज़रूरत है कि क्या मौजूदा प्रदर्शन आपको सूट करता है? उदाहरण के लिए, यदि आप एक गेम विकसित कर रहे हैं, तो "औसत" हार्डवेयर और "मध्यम" सेटिंग्स पर न्यूनतम एफपीएस क्या है? अगर यह नीचे गिरता है, 30 कहते हैं, तो खिलाड़ी इसे नोटिस करेंगे। यहां तक ​​कि अगर औसत फ्रेम दर 60 एफपीएस है, तो यह न्यूनतम एफपीएस है जो खेल की भावना को निर्धारित करता है - "धीमा" या "आसानी से काम करता है"। यदि यह एक वेबसाइट है, तो उपयोगकर्ताओं के लिए पेज कब तक खुलता है? यदि यह समय एक दूसरा विभाजन है, तो उपयोगकर्ता अधिक सक्रिय होंगे और आपकी साइट के साथ काम करने से संतुष्टि प्राप्त करेंगे।

मान लीजिए कि आप समझते हैं कि आप (या आपके वरिष्ठ, हेहे) वर्तमान आवेदन प्रदर्शन के साथ सहज नहीं हैं। क्या करें?

1. उपाय


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

विकसित करते समय, अड़चनों की पहचान करने के लिए प्रोफाइलिंग का उपयोग करना अक्सर सुविधाजनक होता है। उदाहरण के लिए, PHP के लिए, फेसबुक से xhprof नामक एक अच्छा प्रोफाइलर है ( उन्होंने इसके बारे में कई बार यहां लिखा है )। यदि आपके पास एक बड़ी और अपरिचित परियोजना है, तो एक प्रोफाइलर कोड में बाधाओं को जल्दी से खोजने का लगभग एकमात्र तरीका है, यदि कोई हो। हालांकि, "नियमित" प्रोफाइलर का उपयोग शायद ही कभी रोज़मर्रा के विकास के दौरान किया जाता है, एक साथ कई कारणों से:
- यहां तक ​​कि सबसे "अच्छा" प्रोफाइल भी आवेदन को धीमा कर देता है
- परिणामों के लिए आपको एक अलग स्थान पर जाने या व्यक्तिगत दर्शकों को चलाने की आवश्यकता होती है
- परिणाम खुद को कहीं संग्रहीत करने की आवश्यकता होती है (प्रोफाइलिंग डेटा आमतौर पर एक महत्वपूर्ण स्थान लेता है)।

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

अधिकांश खेलों में, आप "डिबगिंग कंसोल" को सक्षम कर सकते हैं, जिसमें, एक नियम के रूप में, आप एफपीएस की संख्या, दृश्य पर वस्तुओं की संख्या आदि देख सकते हैं। अपेक्षाकृत हाल तक, मिनीक्राफ्ट में प्रत्येक फ्रेम के लिए समय के वितरण के साथ एक आरेख शामिल था: एक रंग ने "भौतिकी" पर खर्च किए गए समय को चित्रित किया, दूसरा - प्रतिपादन।

आप कई अलग-अलग चीजों को माप सकते हैं, लेकिन वेब परियोजनाओं के लिए, अधिकांश समय डेटाबेस पर या अन्य सेवाओं तक पहुंचने में खर्च किया जाता है। यदि आप किसी प्रकार के तैयार ढांचे का उपयोग नहीं कर रहे हैं, या यदि आपके पसंदीदा ढांचे में डिबग पैनल शामिल नहीं है, तो भी ऐसा कोड कहीं न कहीं शुरू करने के लिए पर्याप्त है:

<?php function sql_query($query) { $start = microtime(true); $result = mysql_query($query); $GLOBALS['SQL_TIME'] += microtime(true) - $start; return $result; } 


2. मैंने कहा, नाप!


आपने अच्छा किया है, सब कुछ टाइमर के साथ कवर किया गया था, सब कुछ विकास के माहौल में अद्भुत है, लेकिन उत्पादन में सब कुछ अलग है? तो, आप गलत तरीके से माप रहे हैं या, अधिक संभावना है, सब कुछ नहीं ... उत्पादन पर उत्पादकता को मापने के बारे में कैसे? यदि आप लिखते हैं, उदाहरण के लिए, PHP में, उत्पादन वातावरण में प्रदर्शन को मापने के लिए एक अद्भुत उपकरण है जो यूडीपी प्रोटोकॉल पर काम करता है, जिसे पिनबा कहा जाता है। इस टूल के आधार पर, आप डिबग पैनल को विकास के दौरान छोड़ सकते हैं और इसके अलावा, "मुकाबला" वातावरण में अपने टाइमर पर रियलटाइम आँकड़े प्राप्त कर सकते हैं। यदि आपने इस तरह से प्रदर्शन को कभी नहीं मापा है, तो आपको अपनी साइट वास्तव में कैसे काम करती है, इसके बारे में बहुत सारी दिलचस्प बातें पता चलेंगी।

सर्वर से पृष्ठ वापसी का समय 100 एमएस है, लेकिन आप अभी भी शिकायत करते हैं कि पृष्ठ लंबे समय तक खुले रहते हैं? ब्राउज़र में निर्मित आउटपुट और प्रदर्शन काउंटर का आकार मापें। शायद आपकी साइट को स्थैतिक डेटा वापस करने के लिए सीडीएन की आवश्यकता है, हो सकता है कि आपको होस्टिंग प्रदाता को बदलने की आवश्यकता हो। जब तक आप मापते हैं कि अड़चन कहां है, आप केवल अनुमान लगा सकते हैं।

3. आलसी होना


आप अक्सर पा सकते हैं कि सभी के लिए कोड में इस पृष्ठ पर कुछ बड़े और अनावश्यक का आरोपण है। उदाहरण के लिए, कुछ बड़े इनिट विधि, जो मौसम के पूर्वानुमान के लिए प्रत्येक वेब अनुरोध के लिए एक अलग साइट पर चढ़ते हैं या स्वचालित तैनाती के साधन के रूप में, परियोजना की जड़ में "गिट पुल ओरिजिनल मास्टर" द्वारा निष्पादित होते हैं। प्रदर्शन विश्लेषण की प्रक्रिया में, आप निश्चित रूप से कई चीजों के पार आएंगे, जिन्हें आप केवल कोड से बाहर फेंक सकते हैं, या "यदि में लपेटें", और वांछित टुकड़े को केवल तभी शामिल कर सकते हैं जब वास्तव में इसकी आवश्यकता हो।

यह बहुत सामान्य है कि पृष्ठ के बड़े टुकड़े व्यावहारिक रूप से अपरिवर्तित रहते हैं (उदाहरण के लिए, किसी पृष्ठ के "शीर्षलेख" और "पाद लेख")। यदि यह मामला है, तो स्पष्ट समाधान या तो पहले से सामग्री उत्पन्न करना है, या इसे कैश में डालना है और हर बार इसे फिर से नहीं खींचना है।

अपने कोड और वास्तविक जीवन में आलसी रहें। हर समय एक ही काम न करें (किसी को किसी की ज़रूरत नहीं है), केवल वही करें जो आपको वास्तव में उपयोगकर्ता के अनुरोध का जवाब देने की आवश्यकता है, और बाकी काम मत करो, या इसे किसी को सौंप दो (उदाहरण के लिए, आपके पास "भारी" हो सकता है, लेकिन बहुत संवेदनशील नहीं हैं देरी करने के लिए, चीजों को वेब पर करने के बजाय क्रोन को सौंप दिया जाना चाहिए)।

4. (अतुल्यकालिक) बैच प्रसंस्करण का उपयोग करें


विभिन्न प्रकार की परियोजनाओं में, आप एक ही तुच्छ डिजाइन त्रुटि को पूरा कर सकते हैं: एक अनुरोध के साथ सब कुछ एक साथ संसाधित करने के बजाय दसियों, सैकड़ों रिकॉर्ड, एक समय में प्रसंस्करण। उदाहरण के लिए, यदि आपको किसी पृष्ठ पर 30 उत्पादों पर डेटा दिखाने की आवश्यकता है, तो फ़ॉर्म के 30 प्रश्नों के बजाय "SELECT ... FROM table WHERE id IN (...)" फ़ॉर्म की एक क्वेरी "SELECT ... FROM table WHERE id = ..." के रूप में बनाएं। अधिकांश डेटाबेस के लिए, 30 पंक्तियों और एक (!) के साथ एक क्वेरी के बीच गति में कोई अंतर नहीं होगा 1 पंक्ति के परिणाम के साथ बिल्कुल। एक नियम के रूप में, आपको बैच प्रसंस्करण को जोड़ने के लिए कोड में बहुत कम संख्या में परिवर्तन की आवश्यकता होती है, और बदले में आपको कई बार गति में वृद्धि होगी, कभी-कभी सैकड़ों बार। यह न केवल SQL प्रश्नों पर लागू होता है, बल्कि बाहरी या आंतरिक सेवाओं के लिए किसी भी कॉल पर भी लागू होता है। कहीं न कहीं नेटवर्क से संपर्क करना हमेशा अनुरोध को संसाधित करने में एक महत्वपूर्ण देरी का परिचय देता है, इसलिए वेब की स्थितियों में अनुरोधों की संख्या को कम से कम करना बहुत ही वांछनीय है।

बैच प्रोसेसिंग को गति देने का एक और तरीका एसिंक्रोनस है। यदि आपकी भाषा इसे अनुमति देती है और आप विभिन्न सेवाओं के अनुरोधों को एक में समाहित कर सकते हैं और उन्हें एसिंक्रोनस रूप से निष्पादित कर सकते हैं, तो आपको प्रतिक्रिया समय में ध्यान देने योग्य कमी, और अधिक सेवाएं, अधिक से अधिक लाभ मिलेगा। यह खराब तरीके से MySQL के लिए लागू होता है, लेकिन धीमी गति से Google Datastore API के साथ काम करते समय लागू होता है।

5. सरल, जटिल भ्रामक


मैं आपको एक उदाहरण देता हूं: आपके पास एक मोटी एसक्यूएल क्वेरी है जो कुछ करती है और इसे (संभवतः) सही ढंग से करती है, लेकिन एक ही समय में लाखों पंक्तियों को स्कैन करके धीरे-धीरे सोओ । एक जटिल SQL क्वेरी को ऑप्टिमाइज़ करने के लिए, पहले आपको इसे सरल बनाने की आवश्यकता है, जो अनावश्यक है, संभवतः संपूर्ण तालिकाओं या नेस्टेड चयनों को बाहर फेंक दें। आपके द्वारा अनावश्यक रूप से हटाए जाने के बाद ही, आप सार्थक अनुकूलन करना शुरू कर सकते हैं। अन्यथा, आप बहुत समय व्यर्थ में बिता सकते हैं, टुकड़े का अनुकूलन कर सकते हैं, जो अंतिम परिणाम को प्रभावित नहीं करता है। अक्सर, विशेष रूप से MySQL के साथ काम करते समय, कई सरल लोगों में एक क्वेरी को विभाजित करते हुए, जिनमें से प्रत्येक मूल एक की तुलना में बहुत तेजी से काम करता है, एक संतोषजनक समाधान हो सकता है।

बड़ी संख्या में लोगों द्वारा विकसित प्रणालियों में, आप अक्सर एक स्पष्ट और अच्छी तरह से डिज़ाइन किए गए कोड के बजाय "लेयरिंग बैसाखी" देख सकते हैं। यह न केवल प्रोग्रामर की कम योग्यता के साथ होता है, बल्कि सामान्य, पुनरावृत्त विकास के साथ भी होता है, बशर्ते कोई निरंतर रिफैक्टिंग न हो। यदि आप पाते हैं कि समस्या इन स्थानों में से एक में है, तो सबसे पहले आपको कोड का थोड़ा सा पुनर्संरचना करने की आवश्यकता है, सबसे पहले, यह समझने के लिए कि यह कैसे काम करता है, और दूसरी बात, यह स्पष्ट रूप से कुछ स्पष्ट रूप से अनावश्यक चीजों को अनुकूलित या बाहर करना संभव है। अक्सर ऐसा होता है कि, केवल कोड को क्रम में रखने के बाद, कोड का प्रदर्शन संतोषजनक हो जाता है और अनुकूलन की आवश्यकता के लिए संबंधित खंड समाप्त हो जाता है।

6. "प्रिय" सुविधाएँ


यह काफी संभव है कि आप पाते हैं कि ऐसी विशेषताएं हैं जो 0.1% उपयोगकर्ताओं द्वारा उपयोग की जाती हैं, लेकिन जो एक ही समय में सर्वर पर आधा प्रतिक्रिया समय लेती हैं। यदि ऐसा है, तो आप या तो इस कार्यक्षमता पर पुनर्विचार करने की कोशिश कर सकते हैं और बदले में कुछ अन्य, "सस्ता" समाधान पेश कर सकते हैं, या डिफ़ॉल्ट रूप से इस सुविधा को वैकल्पिक और अक्षम बना सकते हैं। यदि उपयोगकर्ता को इसकी आवश्यकता है, तो वह इसे वापस चालू कर देगा।

7. कैशिंग


अगर कुछ और मदद नहीं करता है, या आपके पास डेटा है जो समय के साथ नहीं बदलता है, तो इसे कैश करें। मैं क्यों तर्क देता हूं कि यह कैश का उपयोग करने के लायक है जब अन्य सभी विकल्पों का उपयोग किया गया है? तथ्य यह है कि जैसे ही आप कैश में उत्परिवर्तनीय डेटा डालना शुरू करते हैं, आपको कैश की प्रासंगिकता पर नजर रखने की आवश्यकता होगी, जो एक बहुत ही कठिन इंजीनियरिंग कार्य है।

उदाहरण: आप प्राथमिक कुंजी आईडी के साथ तालिका तालिका में अलग-अलग रिकॉर्ड कैश करते हैं। एक रिकॉर्ड - प्रपत्र "टेबल_ <आईडी>" के कैश में एक कुंजी। अब कल्पना करें कि आपको एक विशिष्ट स्थिति ("अद्यतन तालिका जहाँ <हालत>") के लिए कई रिकॉर्ड अपडेट करने की आवश्यकता है। इस मामले में कैश फ्लश कैसे करें? सरल, लेकिन बहुत ही समय लेने वाले निर्णयों में से एक इस स्थिति को पूर्व-चयन करना है, आईडी द्वारा सभी प्रविष्टियों को कैश में फ्लश करना, और फिर अपडेट करना। लेकिन क्या होगा, अगर चयन के बीच, कैश फ्लश करना, और अपडेट करना, एक और अनुरोध "वेजेज"? कुछ इस तरह:
पहला अनुरोध:
1. जहाँ <हालत> तालिका से आईडी का चयन करें
2. memcache आईडी हटाएं



6. अद्यतन तालिका सेट ... जहां <हालत>
दूसरी समानांतर क्वेरी:


3. मेमेचे को "टेबल -9" मिलता है - खाली, कैश पहले ही रीसेट हो चुका है
4. select ... टेबल से जहाँ id = N
5. memcache सेट "table_N" - पुराने डेटा को कैश पर सेट करें


बहुत करीने से लिखे गए कोड के बिना एक के बजाय दो डेटा स्रोतों की उपस्थिति अनिवार्य रूप से उनके वंशजीकरण की ओर ले जाती है और, कैश के मामले में, असंगत या पुराने डेटा के रूप में साइट पर अप्रिय कलाकृतियों के लिए, "टूटे हुए" काउंटर, आदि।

बेशक, बड़ी संख्या में ऐसे उदाहरण हैं जहां कैशिंग का उपयोग उत्पादकता बढ़ाने के लिए सफलतापूर्वक किया जाता है, लेकिन, अन्य सभी विकल्पों पर विचार करने के बाद फिर से। ऑपरेटिंग सिस्टम में, धीमे मीडिया वाले संचालन को कैश किया जाता है (रीडिंग केवल कैश की जाती है, लेखन बफ़र किया जाता है, जो कभी-कभी डेटा भ्रष्टाचार या फ़ाइल सिस्टम संरचना की ओर जाता है)। यह काम की गति में एक महत्वपूर्ण योगदान देता है, लेकिन अगर आपने कभी एसएसडी और हार्ड ड्राइव के साथ काम करने के उपयोगकर्ता अनुभव की तुलना की है, तो आप कभी भी कैशिंग के बावजूद, बाद वाले का उपयोग नहीं करना चाहेंगे। प्रोसेसर कई कैश स्तरों का उपयोग करते हैं, क्योंकि विभिन्न आकारों की मेमोरी परिमाण के आदेशों द्वारा गति में भिन्न होती है (हार्ड डिस्क के लिए रजिस्टर मेमोरी और 10 एमएस के एक्सेस समय की तुलना करें - अंतर 10 मिलियन गुना है!), इसलिए आर्किटेक्चर की एक महत्वपूर्ण जटिलता अभी भी उचित है ( विकिपीडिया से लिया गया चित्रण)।

निष्कर्ष


तो, हमने (वेब) अनुप्रयोगों के प्रदर्शन को बेहतर बनाने के लिए बुनियादी तरीकों की जांच की, मुख्य रूप से PHP + MySQL बंडल को सबसे आम माना। मैं व्यक्तिगत रूप से अनुकूलन के लिए उपरोक्त तरीकों का उपयोग करता हूं, और अब तक मैंने कई बार परियोजनाओं को गति देने के लिए बहुत प्रयास किए बिना, कभी-कभी दसियों बार, उनमें से सबसे बड़े दिनों के लिए शाब्दिक रूप से खर्च करते हुए :)। मुझे उम्मीद है कि अगर लेख आपको अनुकूलन करना नहीं सिखाता है, तो कम से कम यह आपको (और आपके सहयोगियों) को सही दिशा में धकेल देगा, और दुनिया थोड़ी बेहतर हो जाएगी।

* पहला चित्रण इस पृष्ठ से लिया गया है (Google के अनुसार)

Source: https://habr.com/ru/post/In208138/


All Articles