Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Ruby

रूबी में महारत हासिल करना:मेमोरी लीक का कुशलतापूर्वक पता लगाना और उसे ठीक करना

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

<पी> इस पोस्ट में, मेमोरी लीक पर दो-भाग की श्रृंखला में से पहला, हम यह देखकर शुरू करेंगे कि रूबी मेमोरी को कैसे प्रबंधित करती है, कचरा संग्रहण (जीसी) कैसे काम करती है, और लीक का पता कैसे लगाया जाता है।

<पी> दूसरे भाग में, हम लीक का पता लगाने में गहराई से उतरेंगे।

<पी> आइए शुरू करें!

रूबी मेमोरी प्रबंधन

<पी> रूबी वस्तुएं ढेर पर संग्रहीत होती हैं, और प्रत्येक वस्तु ढेर पर एक स्लॉट भरती है।

<पी> रूबी 3.1 से पहले, ढेर पर सभी स्लॉट एक ही आकार के थे - सटीक होने के लिए 40 बाइट्स। एक खांचे में फिट होने के लिए बहुत बड़ी वस्तुओं को ढेर के बाहर संग्रहीत किया गया था। प्रत्येक स्लॉट में एक संदर्भ शामिल होता है कि वस्तुओं को कहाँ ले जाया गया था।

<पी> रूबी 3.1 में, String के लिए परिवर्तनीय चौड़ाई आवंटन वस्तुओं का विलय कर दिया गया। जल्द ही, परिवर्तनीय चौड़ाई आवंटन एलोबजेक्ट प्रकारों के लिए आदर्श होगा।

<पी> परिवर्तनीय चौड़ाई आवंटन का लक्ष्य कैशेलोकैलिटी में सुधार करके प्रदर्शन में सुधार करना है - किसी ऑब्जेक्ट की सभी जानकारी दो मेमोरी स्थानों के बजाय एक ही स्थान पर संग्रहीत की जाएगी।

<पी> इसे मेमोरी प्रबंधन के (कुछ हिस्सों) को भी सरल बनाना चाहिए। फिलहाल, दो 'ढेर' हैं:

  • रूबी हीप (या GC हीप) जो छोटी रूबी वस्तुओं को संग्रहीत करता है।
  • सी हीप (या मॉलोक/क्षणिक हीप) जो बड़ी वस्तुओं को संग्रहीत करता है।
<पी> एक बार जब परिवर्तनीय चौड़ाई आवंटन मानक हो जाता है, तो बाद वाले ढेर की कोई आवश्यकता नहीं होनी चाहिए।

<पी> ढेर एक दिए गए आकार (डिफ़ॉल्ट रूप से 10,000 स्लॉट) पर शुरू होता है और जैसे ही वे बनाए जाते हैं, ऑब्जेक्ट क्षेत्रों को मुफ्त स्लॉट के लिए निर्दिष्ट कर दिया जाता है। जब रूबी एक ऑब्जेक्ट बनाने की कोशिश करती है और कोई मुफ्त स्लॉट उपलब्ध नहीं होता है, तो कुछ मुफ्त स्लॉट उपलब्ध कराने के लिए गारबेज कलेक्शन (जीसी) होता है।

<पी> यदि जीसी के बाद बहुत कम मुफ्त स्लॉट हैं, तो हीप का विस्तार किया जाएगा (इस पर थोड़ी देर बाद और अधिक)।

<पी> यहां वे कारक हैं जिन्हें आप उनके पर्यावरण चर के साथ नियंत्रित कर सकते हैं:

  • ढेर का प्रारंभिक आकार - RUBY_GC_HEAP_INIT_SLOTS
  • जीसी होने के बाद उपलब्ध होने वाले निःशुल्क स्लॉट की संख्या - RUBY_GC_HEAP_FREE_SLOTS
  • ढेर का विस्तार - RUBY_GC_HEAP_GROWTH_FACTOR द्वारा किया जाता है

रूबी में कचरा संग्रहण

<पी> रूबी में कचरा संग्रहण 'दुनिया को रोक देता है' - जीसी होने पर कोई अन्य प्रक्रिया नहीं होती है। रूबी में कचरा संग्रहण (2.1 से) भी पीढ़ीगत है , जिसका अर्थ है कि कचरा संग्राहक के दो मोड हैं:

  • मामूली जीसी - 'युवा' वस्तुओं (हाल ही में बनाई गई वस्तुएं) का निरीक्षण करता है
  • मेजर जीसी - 'पुरानी' वस्तुओं के साथ-साथ 'युवा' वस्तुओं (सभी) का निरीक्षण करता है ऑब्जेक्ट्स)
<पी> ध्यान दें :एक 'पुरानी' वस्तु बच गई है 3 जीसी चलता है, बड़ा या छोटा।

<पी> जब ढेर भर जाता है, तो सबसे पहले माइनर जीसी को लागू किया जाता है। यदि यह सीमा से नीचे पर्याप्त स्लॉट खाली नहीं कर पाता है, तो प्रमुख जीसी लागू किया जाएगा। केवल तभी, यदि अभी भी पर्याप्त खाली स्लॉट नहीं हैं, तो ढेर का विस्तार किया जाएगा।

<पी> मेजर जीसी माइनर जीसी से अधिक महंगी है क्योंकि यह अधिक वस्तुओं को देखती है।

<पी> जेनरेशनल जीसी अधिक प्रदर्शनशील क्यों है इसके पीछे सिद्धांत यह है कि वस्तुएं आमतौर पर दो श्रेणियों में आती हैं:

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

<पी> जब आपके पास रिसाव होता है, तो आप ऐसी वस्तुएं बनाते हैं जिन्हें साफ नहीं किया जा सकता - अधिक से अधिक old वस्तुएं. इसका मतलब यह है कि प्रमुख (महंगा) GC जितनी बार चलना चाहिए उससे कहीं अधिक बार चलेगा। चूँकि जब GC चल रहा होता है तो कुछ भी नहीं चलता है, यह वह समय है जिसे आप बर्बाद करते हैं।

<पी> रूबी में मेमोरीलेआउट और गारबेज कलेक्टर पर आगे पढ़ने के लिए मैंने इस लेख के अंत में कुछ लिंक छोड़े हैं।

रूबी में मेमोरी लीक कैसा दिखता है?

<पी> आप किसी भी यूनिक्स सिस्टम पर उपलब्ध सरल टूल का उपयोग करके मेमोरी लीक देख सकते हैं। उदाहरण के तौर पर निम्नलिखित कोड लें।

 <पी> इस कोड को 'लीक' कहना थोड़ा अनुचित है - यह जो कुछ करता है वह लीक है! —लेकिन यह हमारे उद्देश्यों को पूरा करता है।

<पी> हम इस प्रोग्राम को एक टर्मिनल और watch में चलाकर कमांड लाइन से रिसाव का काफी सरलता से निरीक्षण कर सकते हैं। -ps के साथ समय के साथ मेमोरी बढ़ती है .

 <पी> pgrep -f "ruby ./leaky.rb" हमारे लिए प्रक्रिया आईडी ढूंढता है, ताकि हम ps को प्रतिबंधित कर सकें केवल उसी प्रक्रिया के लिए आउटपुट जिसमें हम रुचि रखते हैं। जैसा कि आप अनुमान लगा सकते हैं, यह grep जैसा है प्रक्रियाओं के लिए.

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

<पी> आपको इस तरह का आउटपुट मिलेगा, जो हर कुछ सेकंड में अपडेट होता है।

 <पी> आपको %MEM देखना चाहिए और RSS बढ़ रहा है. वे हैं:

  • %MEM - होस्ट मशीन पर मेमोरी के प्रतिशत के रूप में प्रक्रिया द्वारा उपयोग की जाने वाली मेमोरी की मात्रा।
  • RSS (निवासी सेट आकार) - प्रक्रिया द्वारा उपयोग की जाने वाली रैम की मात्रा बाइट्स में।
<पी> यदि आपके पास कोई रिसाव है तो यह बुनियादी ओएस-मात्र जानकारी पता लगाने के लिए पर्याप्त है - यदि मेमोरी बढ़ती रहती है, तो इसका मतलब है कि आप ऐसा कर रहे हैं!

कचरा कलेक्टर मॉड्यूल के साथ रूबी लीक का पता लगाएं

<पी> हम GC के साथ रूबी कोड के भीतर भी लीक का पता लगा सकते हैं मॉड्यूल.

 <पी> GC.stat विधि बहुत सारी उपयोगी जानकारी के साथ एक हैश लौटा देगी। यहां, हमारी रुचि :heap_live_slots में है , जो कि ढेर पर उपयोग में आने वाले स्लॉट की संख्या है। यह :heap_free_slots के विपरीत है .लूप के अंत में, हम एक प्रमुख GC को बाध्य करते हैं और उपयोग किए गए स्लॉट की संख्या प्रिंट करते हैं, अर्थात, GC के बाद बची हुई वस्तुओं की संख्या।

<पी> जब हम अपना छोटा सा कार्यक्रम चलाते हैं, तो हम देखते हैं कि इसमें अनंत काल तक वृद्धि होती रहती है। हमारे पास एक रिसाव है! हम GC.stat(:old_objects) का भी उपयोग कर सकते थे समान प्रभाव के लिए.

<पी> जबकि GC मॉड्यूल का उपयोग यदि देखने के लिए किया जा सकता है हमारे पास एक रिसाव है और (यदि आप अपने puts के साथ पुनः चतुर हैं कथन) जहां रिसाव हो सकता है, हम उस प्रकार की वस्तुओं को देख सकते हैं जो ObjectSpace के साथ लीक हो सकती हैं। मॉड्यूल.

 <पी> ObjectSpace.count_objects विधि जीवित वस्तुओं की गिनती के साथ एक हैश लौटाती है। T_STRING उदाहरण के लिए, मेमोरी में लाइव स्ट्रिंग्स की संख्या है। हमारे बल्कि लीक प्रोग्राम के लिए, यह मान प्रत्येक लूप के साथ बढ़ता है, यहां तक ​​कि जीसी के बाद भी। हम देख सकते हैं कि हम स्ट्रिंग ऑब्जेक्ट लीक कर रहे हैं।

ऐपसिग्नल के साथ उत्पादन में एप्लिकेशन प्रदर्शन की निगरानी

<पी> ps के साथ खेलते समय और GC खिलौना परियोजनाओं के लिए यह एक समझदारी भरा मार्ग हो सकता है—वे उपयोग करने में मज़ेदार और जानकारीपूर्ण भी हैं! — मैं नहीं करुंगा इन्हें प्रोडक्शन ऐप्स में अपने मेमोरी लीक डिटेक्शन समाधान के रूप में अनुशंसित करें।

<पी> यह वह जगह है जहां आप एप्लिकेशन परफॉर्मेंस मॉनिटरिंग (एपीएम) टूल का उपयोग करेंगे। यदि आप एक बहुत बड़ी कंपनी हैं, तो आप इन्हें स्वयं बना सकते हैं। हालाँकि, छोटे परिधानों के लिए, एपीएम को तुरंत चुनना ही एक रास्ता है। आपको मासिक सदस्यता का भुगतान करने की आवश्यकता है, लेकिन वे जो जानकारी प्रदान करते हैं वह इसकी भरपाई कर देती है।

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

<पी> रूबी में महारत हासिल करना:मेमोरी लीक का कुशलतापूर्वक पता लगाना और उसे ठीक करना

<पी> और यहाँ परिनियोजन के बाद एक अस्वास्थ्यकर ऐप है:

<पी> रूबी में महारत हासिल करना:मेमोरी लीक का कुशलतापूर्वक पता लगाना और उसे ठीक करना

<पी> ऐपसिग्नल जीसी और हीप स्लॉट जैसे रूबी वीएम आंकड़ों को भी सामने लाएगा, जो आपको मेमोरी लीक के लिए और भी स्पष्ट संकेत दे सकता है। यदि लाइव स्लॉट की संख्या बढ़ती रहती है, तो आपके पास एक रिसाव है!

<पी> रूबी में महारत हासिल करना:मेमोरी लीक का कुशलतापूर्वक पता लगाना और उसे ठीक करना

<पी> रूबी के लिए ऐपसिग्नल के बारे में और पढ़ें।

समाप्ति और आगे की पढ़ाई

<पी> इस पोस्ट में, हमने रूबी के मेमोरी प्रबंधन और कचरा संग्रहकर्ता का एक त्वरित दौरा किया। फिर हमने निदान किया कि यूनिक्स टूल और रूबी के जीसी मॉड्यूल का उपयोग करके मेमोरी लीक का पता कैसे लगाया जाए।

<पी> अगली बार, हम देखेंगे कि memory_profiler का उपयोग कैसे करें और derailed_benchmarks लीक ढूंढने और ठीक करने के लिए।

<पी> इस बीच, आप हमारे द्वारा उपयोग किए गए टूल के बारे में अधिक पढ़ सकते हैं:

  • watch
  • ps
  • pgrep
<पी> अतिरिक्त आगे पढ़ना:

  • GC मॉड्यूल दस्तावेज़ीकरण
  • ObjectSpace मॉड्यूल दस्तावेज़ीकरण
  • कचरा संग्रहण गहन गोता
  • परिवर्तनीय चौड़ाई आवंटन
<पी> कोडिंग का आनंद लें, अगली बार मिलते हैं!

<पी> पी.एस. यदि आप प्रेस से हटते ही रूबी मैजिक पोस्ट पढ़ना चाहते हैं, तो हमारे रूबी मैजिक न्यूज़लेटर की सदस्यता लें और एक भी पोस्ट न चूकें!
  1. बेज़ियर वक्र खींचने के लिए HTML कैनवास बेज़ियर वक्र खींचने के लिए HTML कैनवास

    बेज़ियर वक्र बनाने के लिए, HTML में BezierCurveTo () विधि का उपयोग करें। आइए सबसे पहले सिंटैक्स देखें - ctx.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y); यहाँ, cp1x - पहले बेज़ियर नियंत्रण बिंदु के x-निर्देशांक का प्रतिनिधित्व करता है cp1y - पहले बेज़ियर नियंत्रण बिंदु के y-निर्देशांक का प्रतिनिधित्व कर

  1. सी/सी ++ में एए पेड़? सी/सी ++ में एए पेड़?

    कंप्यूटर विज्ञान में AA ट्री को संतुलित ट्री के रूप में परिभाषित किया गया है, जो ऑर्डर किए गए डेटा को कुशलतापूर्वक संग्रहीत करने और पुनर्प्राप्त करने के लिए लागू किया गया है। एए पेड़ों को लाल-काले पेड़ की विविधता के रूप में माना जाता है, बाइनरी सर्च ट्री का एक रूप जो प्रविष्टियों के कुशल जोड़ और विल

  1. रेडिस और अपाचे काफ्का के साथ समय-श्रृंखला डेटा को संसाधित करना रेडिस और अपाचे काफ्का के साथ समय-श्रृंखला डेटा को संसाधित करना

    RedisTimeSeries एक Redis मॉड्यूल है जो Redis में मूल समय-श्रृंखला डेटा संरचना लाता है। समय-श्रृंखला समाधान, जो पहले सॉर्ट किए गए सेट (या रेडिस स्ट्रीम) के शीर्ष पर बनाए गए थे, रेडिसटाइमसीरीज़ सुविधाओं जैसे उच्च-वॉल्यूम सम्मिलन, कम-विलंबता रीड, लचीली क्वेरी भाषा, डाउन-सैंपलिंग, और बहुत कुछ से लाभ उठा