सर्वर समाप्ति पर वस्तुओं को सही ढंग से निपटाना


9

मैं एक बड़े C ++ प्रोजेक्ट पर काम कर रहा हूं। इसमें एक सर्वर होता है जो REST API को उजागर करता है, जिसमें बहुत व्यापक प्रणाली के लिए एक सरल और उपयोगकर्ता के अनुकूल इंटरफेस प्रदान करता है जिसमें कई अन्य सर्वर शामिल होते हैं। कोडबेस काफी बड़ा और जटिल है, और एक उचित डिजाइन के बिना समय के माध्यम से विकसित हुआ है। मेरा कार्य नई सुविधाओं को लागू करना और पुराने कोड को ठीक करना / ठीक करना है ताकि इसे अधिक स्थिर और विश्वसनीय बनाया जा सके।

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

मेरा विचार यह सुनिश्चित करना है कि सभी वस्तुओं को समाप्ति से पहले निपटाया जाए, लेकिन जब मैंने यह प्रस्ताव रखा, तो मेरे सहयोगियों और मेरे बॉस ने मुझे यह बताते हुए विरोध किया कि ओएस वैसे भी उस स्मृति को मुक्त करने जा रहा है (जो हर किसी के लिए स्पष्ट है) और वस्तुओं का निपटान करना सर्वर के शटडाउन को धीमा कर देगा (जो, इस समय, मूल रूप से एक कॉल है std::exit)। मैंने जवाब दिया कि "स्वच्छ" शटडाउन प्रक्रिया होने का मतलब यह नहीं है कि किसी को इसका उपयोग करना चाहिए। हम हमेशा फोन कर सकते हैं std::quick_exitया सिर्फ kill -9प्रक्रिया अगर हम अधीर लग रहा है।

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

आपके क्या विचार हैं? क्या मैं एक व्यर्थ प्रयास कर रहा हूं? यदि नहीं, तो मैं अपने सहयोगियों और अपने बॉस को कैसे मना सकता हूं? यदि हां, तो मुझे इसके बजाय क्यों और क्या करना चाहिए?


प्रदर्शन तर्क के अलावा (जो उचित है!), क्या यह लंबे समय से जीवित वस्तुओं को अलग करने और उनके लिए सफाई-अप कोड जोड़ने का बहुत प्रयास है?
Doc Brown

जवाबों:


7

सर्वर प्रक्रिया के लिए एक स्विच जोड़ें जिसका उपयोग वैलेग्रिंड माप के दौरान किया जा सकता है जो सभी मेमोरी को रिलीज़ करेगा। आप इस स्विच को परीक्षण के लिए उपयोग कर सकते हैं। प्रभाव सामान्य कार्यों के दौरान कम से कम हो जाएगा।

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

सामान्य प्रदर्शन को प्रभावित नहीं करते हुए हमारे परीक्षण के लिए यह एक अच्छा समझौता था।


1
+1 व्यावहारिकता FTW। माप में मूल्य है, लेकिन तेजी से बंद होने में भी मूल्य है।
रॉस पैटरसन

2
कमांड लाइन स्विच के विकल्प के रूप में, आप #ifdef DEVUG ब्लॉक के अंदर स्थायी वस्तुओं को हटाने पर भी विचार कर सकते हैं।
जूल्स

3

यहाँ कुंजी यह है:

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

यह बहुत अधिक सीधे तौर पर तात्पर्य है कि आपका कोडबेस आशा और स्ट्रिंग से ज्यादा कुछ भी एक साथ नहीं है। सक्षम C ++ प्रोग्रामर के पास डबल फ़्रीज़ नहीं हैं।

आप पूरी तरह से एक व्यर्थ प्रयास कर रहे हैं- जैसा कि, आप वास्तविक समस्या के एक छोटे से लक्षण को संबोधित कर रहे हैं, जो यह है कि आपका कोड अपोलो 13 सेवा मॉड्यूल के रूप में विश्वसनीय है।

यदि आप अपने सर्वर को RAII के साथ सही ढंग से प्रोग्राम करते हैं, तो ये समस्याएँ नहीं होंगी, और आपके प्रश्न की समस्या समाप्त हो जाएगी। इसके अलावा, आपका कोड वास्तव में समय-समय पर सही तरीके से निष्पादित हो सकता है। इस प्रकार, यह स्पष्ट रूप से सबसे अच्छा विकल्प है।


निश्चित रूप से समस्या अधिक तस्वीर में है। हालांकि, यह बहुत दुर्लभ है कि कोई संसाधन और बेहतर आकार के लिए किसी परियोजना को फिर से लिखने / फिर से लिखने की अनुमति पा सकता है।
सेंगिज

@CengizCan: यदि आप बग्स को ठीक करना चाहते हैं, तो आपको रिफ्लेक्टर करने की आवश्यकता है। यह वैसे काम करता है।
डेडएमजेड डीएएम

2

वर्गीकरण के माध्यम से अपने सहयोगियों के साथ चर्चा को कम करने के लिए एक अच्छा तरीका होगा। एक बड़े कोड आधार को देखते हुए, निश्चित रूप से एक ही कारण नहीं है, बल्कि लंबे समय तक रहने वाली वस्तुओं के लिए कई (पहचानने योग्य) कारण हैं।

उदाहरण:

  • लंबे समय तक जीवित वस्तुएं जो किसी के द्वारा संदर्भित नहीं होती हैं (वास्तविक लीक)। यह एक प्रोग्रामिंग लॉजिक एरर है। कम प्राथमिकता वाले उन लोगों को ठीक करें, जो समय के साथ बढ़ने के लिए आपकी मेमोरी फ़ुटप्रिंट के लिए ज़िम्मेदार हैं (और आपके एप्लिकेशन की गुणवत्ता बिगड़ती है)। यदि वे समय के साथ आपकी मेमोरी फुटप्रिंट को बड़ा करते हैं तो उन्हें उच्च प्राथमिकता के साथ ठीक करें।

  • लंबे समय तक रहने वाली वस्तुएं, जो अभी भी संदर्भित हैं, लेकिन अब उपयोग नहीं की जाती हैं (प्रोग्राम लॉजिक के कारण), लेकिन जो आपके मेमोरी फ़ुटप्रिंट को नहीं बढ़ाती हैं। कोड की समीक्षा करें और उन अन्य बगों को खोजने का प्रयास करें जो उस तक ले जाते हैं। यदि यह एक जानबूझकर (प्रदर्शन) अनुकूलन है, तो कोड आधार पर टिप्पणी जोड़ें।

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

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

  • "साझा वस्तुएं" - कई अन्य वस्तुओं द्वारा उपयोग की जाने वाली (संदर्भित) वस्तुएं और कोई नहीं जानता कि वास्तव में कब उन्हें मुक्त करने के लिए बचत होती है। उन्हें गिनती की गई वस्तुओं के संदर्भ में बदलने पर विचार करें।

एक बार जब आप उन अक्षम वस्तुओं के वास्तविक कारणों को वर्गीकृत कर लेते हैं, तो केस चर्चा से मामला दर्ज करना और एक प्रस्ताव ढूंढना बहुत आसान होता है।


0

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

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

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

http://en.wikipedia.org/wiki/Active_record_pattern

C ++ में, मेरे पास प्रत्येक सक्रिय रिकॉर्ड में सर्वर के लिए एक कमजोर_प्राथर होता है, जो सर्वर कनेक्शन के अंधेरे होने पर चीजों को समझदारी से फेंक सकता है। ये कक्षाएं या तो आलसी या बैचयुक्त हो सकती हैं, जो आपकी आवश्यकताओं पर निर्भर करती हैं, लेकिन उन वस्तुओं का जीवनकाल केवल वहीं होना चाहिए जहां उनका उपयोग किया जाता है।

यह सभी देखें:

क्या प्रक्रिया से बाहर निकलने से पहले संसाधनों को मुक्त करना समय की बर्बादी है?

अन्य


This reeks of global variablesआप "उन हजारों वस्तुओं से कैसे जाते हैं जिन्हें" उन्हें वैश्विक होना चाहिए "को मुक्त किया जाना चाहिए?" यह काफी तर्क की छलांग है।
डोभाल

0

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

यदि आप इस विचार से परिचित नहीं हैं, तो यहां c ++ में कस्टम मेमोरी आवंटन को नपुंसक बनाने के बारे में एक लेख दिया गया है , हालांकि ध्यान दें कि आपका समाधान उस लेख के उदाहरणों की तुलना में अच्छी तरह से सरल हो सकता है क्योंकि आपको विलोपन को संभालने की आवश्यकता नहीं है। !

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