कोड बेस के खिलाफ दृष्टिकोण समान रूप से धीमा हो रहा है


11

हम मध्यम आकार के C ++ कोड बेस (10Mloc) पर काम कर रहे हैं जो हमारे अनुकूलन प्रयासों के माध्यम से समान रूप से धीमा हो रहा है

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

क्या कोई सफल कार्यप्रणाली है जो यह तय करने में मदद करती है कि विश्वव्यापी रूप से बेहतर प्रदर्शन करने वाले समाधान के लिए एक कोड आधार के विकास को लेने के लिए क्या होता है जो आसान अनुकूलन अवसरों से आसानी से भ्रमित नहीं होते हैं?

संपादित करें

इस प्रश्न का उत्तर देने के लिए कि हम वर्तमान में कैसे प्रोफाइल बनाते हैं:

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


10
10Mloc वास्तव में बहुत बड़ी परियोजना है
Blови

1
इसकी गणना 10 मिलियन (SI उपसर्ग) के रूप में होती है sloc। मैंने इसे "मध्यम आकार" कहा, क्योंकि मुझे नहीं पता कि यहां "बड़ा" क्या माना जाता है।
बेंजामिन बैनियर

5
बहुत यकीन है कि 10 मिलियन हर जगह कम से कम बड़ा है और शायद सबसे बड़ा स्थान है।
रायथल

1
बहुत बढ़िया, धन्यवाद @ हॉन 10M LOC के लिए ऐसा लगता है कि आप हार्डवेयर स्तर पर लगभग बहुत कम अनुकूलन कर रहे हैं? पारंपरिक OOP (AOS "संरचनाओं की सरणी") कैश पर बहुत ही अक्षम है, क्या आपने अपनी कक्षाओं को SOA (सरणियों की संरचना) के रूप में पुनर्व्यवस्थित करने की कोशिश की है, ताकि आपका कोड जिस डेटा बिंदु पर काम कर रहा है वह मेमोरी में सुसंगत हो? कई मशीनों के साथ आप संचार रुकावटों में चल रहे हैं या समय के साथ सिंक्रनाइज़ेशन खा रहे हैं? अंतिम प्रश्न, क्या आप स्ट्रीमिंग डेटा के उच्च संस्करणों के साथ काम कर रहे हैं या यह ज्यादातर आपके डेटा सेट पर जटिल संचालन की समस्या है?
पैट्रिक ह्यूजेस

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

जवाबों:


9

मैं इस समस्या के लिए एक सामान्य-उद्देश्य दृष्टिकोण के बारे में नहीं जानता, लेकिन दो संबंधित दृष्टिकोणों ने अतीत में मेरे लिए अच्छी तरह से काम किया: बेहतर शर्तों की कमी के लिए, मैंने उन्हें गुच्छा और क्षैतिज अनुकूलन कहा

बंचिंग अप्रोच एक एकल, धीमी गति से चलने वाले, अति विशिष्ट ऑपरेशन के साथ बड़ी संख्या में लघु, तेज संचालन को बदलने का एक प्रयास है जो अंततः एक ही परिणाम उत्पन्न करता है।

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

क्षैतिज अनुकूलन एक संबंधित तकनीक है जब आप "सुस्ती" को समाप्त करते हैं जो आपके सिस्टम के कई घटकों के बीच आपके निष्पादन वातावरण की एक विशेष सुविधा का उपयोग करके वितरित किया जाता है।

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


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

3

इसने महंगे शुरुआती निर्णय को बहुत बाद में स्पष्ट किया। अब हम एक ऐसे बिंदु पर हैं जहां आगे अनुकूलन बहुत अधिक महंगे हैं क्योंकि उन्हें कोड आधार के बड़े हिस्से को फिर से लिखना होगा।

जब आप इस पुनर्लेखन को शुरू करते हैं तो आपको कई काम अलग-अलग तरीके से करने होते हैं।

प्रथम। और सबसे महत्वपूर्ण है। "अनुकूलन" रोकें। "अनुकूलन" बहुत ज्यादा मायने नहीं रखता है। जैसा कि आपने देखा है, केवल थोक मामलों को फिर से लिखना है।

इसलिए।

दूसरा। हर डेटा संरचना और एल्गोरिथ्म पसंद के निहितार्थ को समझें।

तीसरा। डेटा संरचना और एल्गोरिथ्म की वास्तविक पसंद "देर से बाध्यकारी" की बात करें। डिज़ाइन इंटरफेस जो इंटरफ़ेस के पीछे उपयोग किए गए कई कार्यान्वयनों में से किसी एक का हो सकता है।

यदि आप अभी (पुनर्लेखन) कर रहे हैं तो बहुत कम, बहुत दर्दनाक होना चाहिए यदि आपको परिभाषित इंटरफेस का एक सेट मिला है जो आपको डेटा संरचना या एल्गोरिथ्म में एक थोक परिवर्तन करने की अनुमति देता है।


1
आपके उत्तर के लिए धन्यवाद। जबकि हमें अभी भी अनुकूलन करने की आवश्यकता है (जो मेरे लिए 1. और 2. के अंतर्गत आता है) मुझे वास्तव में पीछे की संगठित सोच पसंद है। 3. डेटा संरचना, एल्गोरिथ्म और पहुंच को देर से और स्पष्ट परिभाषित करके, किसी को कई पर एक हैंडल करने में सक्षम होना चाहिए हम समस्याओं का सामना कर रहे हैं। एक सुसंगत भाषा में डालने के लिए धन्यवाद।
बेंजामिन बैनियर

आपको वास्तव में अनुकूलित करने की आवश्यकता नहीं है। एक बार जब आपके पास सही डेटा संरचना होती है, तो अनुकूलन को प्रयासों की बर्बादी के रूप में दिखाया जाएगा। प्रोफाइलिंग यह दिखाएगी कि आपके पास गलत डेटा संरचना और गलत एल्गोरिथ्म कहां है। के बीच प्रदर्शन अंतर के साथ बेवकूफ बनाना ++और +=1अप्रासंगिक और लगभग असहनीय होगा। यह आप पिछले करने के लिए बात है ।
S.Lott

1
सभी खराब एल्गोरिदम को शुद्ध तर्क द्वारा नहीं पाया जा सकता है। एक बार थोड़ी देर में किसी को बैठकर प्रोफाइल बनाने की जरूरत है। यह पता लगाने का एकमात्र तरीका है कि क्या प्रारंभिक अनुमान सही था। यह वास्तविक लागत (बिग + कॉन्स्ट) का अनुमान लगाने का एकमात्र तरीका है।
बेंजामिन बैनियर

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

3

एक अच्छा प्रैक्टिकल ट्रिक है अपनी यूनिट टेस्ट सूट का इस्तेमाल परफॉर्मेंस टेस्ट सूट के रूप में करना

निम्नलिखित दृष्टिकोण ने मेरे कोड बेस में अच्छा काम किया:

  1. सुनिश्चित करें कि आपकी इकाई परीक्षण कवरेज अच्छी है (आपने यह पहले से ही किया है, ठीक है?)
  2. सुनिश्चित करें कि आपके टेस्ट रनिंग फ्रेमवर्क रिपोर्ट्स प्रत्येक व्यक्तिगत टेस्ट पर रनटाइम हैं । यह महत्वपूर्ण है क्योंकि आप यह जानना चाहते हैं कि धीमा प्रदर्शन कहां हो रहा है।
  3. यदि कोई परीक्षण धीरे-धीरे चल रहा है, तो इस क्षेत्र में डाइविंग और लक्ष्य अनुकूलन के तरीके के रूप में उपयोग करें । प्रदर्शन के मुद्दे की पहचान करने से पहले अनुकूलन को समय से पहले माना जा सकता है, इसलिए इस दृष्टिकोण के बारे में बड़ी बात यह है कि आपको पहले खराब प्रदर्शन के ठोस सबूत मिलते हैं। यदि आवश्यक हो, तो परीक्षण को छोटे परीक्षणों में विभाजित करें जो विभिन्न पहलुओं को बेंचमार्क करते हैं ताकि आप पहचान सकें कि जड़ समस्या कहां है।
  4. यदि एक परीक्षण बहुत तेजी से चलता है जो आमतौर पर अच्छा होता है, हालांकि आप अलग-अलग मापदंडों के साथ परीक्षण को लूप में चलाने पर विचार कर सकते हैं। यह इसे एक बेहतर प्रदर्शन परीक्षण में बनाता है और पैरामीटर स्थान के आपके परीक्षण कवरेज को भी बढ़ाता है।
  5. कुछ अतिरिक्त परीक्षण लिखें जो विशेष रूप से प्रदर्शन को लक्षित करते हैं, उदाहरण के लिए 1,000 नियम अनुप्रयोगों को पूरा करने के लिए अंत-से-अंत लेनदेन समय या समय। यदि आपके पास विशिष्ट गैर-कार्यात्मक प्रदर्शन आवश्यकताएं हैं (उदाहरण <300ms प्रतिक्रिया समय), तो परीक्षण को विफल कर दें यदि यह बहुत लंबा लगता है।

यदि आप यह सब करते रहते हैं, तो समय के साथ आपके कोड आधार के औसत प्रदर्शन में सुधार होना चाहिए।

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


मुझे तकनीक पसंद है - चतुर - हॉवेरे, यह माइक्रो ऑप्टिमाइज़ेशन है और एक स्थानीय न्यूनतम में सुधार करेगा - यह वास्तु संबंधी समस्याओं को हल नहीं करेगा जो आपको वैश्विक न्यूनतम हिट करने की अनुमति देता है
जसकोंक

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

1

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

वास्तव में, उस मामले में, वास्तविक समस्या प्रोफाइलिंग द्वारा नहीं पाई गई थी, लेकिन भाग्यशाली अंतर्दृष्टि द्वारा।

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

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

यह "हॉट स्पॉट" नहीं है।

यह एक विवरण है जो आप देखते हैं कि आप क्या करते हैं, यह सच है कि यह समय का एक बड़ा प्रतिशत है। यह खोज करने के लिए सरल बनाता है, लेकिन क्या इसे ठीक करना आसान है, यह इस बात पर निर्भर करता है कि इसके लिए कितना फिर से लिखना आवश्यक है।

(इस दृष्टिकोण से अक्सर एक समालोचना होती है, कि सांख्यिकीय वैधता के लिए नमूनों की संख्या बहुत कम है। पीडीएफ की स्लाइड 13 पर इसका उत्तर दिया गया है। संक्षेप में - हां, संभावित बचत के "माप" में उच्च अनिश्चितता है, लेकिन 1) उस संभावित बचत का अपेक्षित मूल्य अनिवार्य रूप से अप्रभावित है, और 2) जब संभावित बचत $ x $ को $ 1 / (1-x) $ द्वारा स्पीडअप अनुपात में अनुवादित किया जाता है, तो यह उच्च (लाभकारी) कारकों की ओर जोरदार तिरछा होता है।)


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

@ हांक: सही है। लेकिन दुख की बात यह है कि इंस्ट्रूमेंटेशन अभी भी इस विचार को संचालित करता है कि प्रदर्शन की समस्याएं स्थानीयकृत हैं और इसलिए दिनचर्या में बिताए समय के कुछ अंशों को मापने के द्वारा पाया जा सकता है, आदि। आप निश्चित रूप से वेलग्रिंड आदि चला सकते हैं, लेकिन यदि आप प्रदर्शन में वास्तविक जानकारी चाहते हैं तो उस स्लाइड शो को देखें। ।
माइक डनलैवी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.