मेमोरी से जुड़ी शब्दावली

मेगिन किर्नी
मेगिन किर्नी

इस सेक्शन में, मेमोरी का विश्लेषण करने में इस्तेमाल होने वाले सामान्य शब्दों के बारे में बताया गया है. साथ ही, यह अलग-अलग भाषाओं के लिए, मेमोरी प्रोफ़ाइल बनाने वाले कई टूल पर लागू होता है.

यहां बताए गए शब्द और सिद्धांत, Chrome DevTools हीप प्रोफ़ाइलर के बारे में बताते हैं. अगर आपने कभी भी Java, .NET या किसी दूसरे मेमोरी प्रोफ़ाइलर का इस्तेमाल किया है, तो आपको इसकी जानकारी देनी होगी.

ऑब्जेक्ट के साइज़

मेमोरी को एक ऐसे ग्राफ़ के रूप में देखें जिसमें प्रिमिटिव टाइप (जैसे कि संख्या और स्ट्रिंग) और ऑब्जेक्ट (असोसिएट सरणियां) शामिल हों. इसे एक-दूसरे से जुड़े हुए कई पॉइंट के साथ इस तरह दिखाया जा सकता है:

मेमोरी का विज़ुअल प्रज़ेंटेशन

कोई ऑब्जेक्ट दो तरीकों से मेमोरी होल्ड कर सकता है:

  • सीधे ऑब्जेक्ट से.
  • साफ़ तौर पर दूसरी चीज़ों को होल्ड करके रखें और इसलिए उन चीज़ों को कूड़ा फेंकने वाले की मदद से अपने-आप नष्ट होने से रोकें. (कम शब्दों में कहें, तो जीसी).

DevTools ("प्रोफ़ाइल) में मिली मेमोरी से जुड़ी समस्याओं की जांच करने के लिए एक टूल" में हीप प्रोफ़ाइलर की मदद से काम करते समय, हो सकता है कि आप जानकारी के कुछ अलग-अलग कॉलम में देखें. इन दो चीज़ों को सबसे अलग माना जाता है, वे हैं शैलो साइज़ और रिटेन्ड साइज़, लेकिन इनसे क्या पता चलता है?

उथला और बनाए रखा गया साइज़

छोटा साइज़

यह मेमोरी का वह आकार है जो खुद ऑब्जेक्ट के पास रहता है.

सामान्य JavaScript ऑब्जेक्ट में, ब्यौरे के लिए और तुरंत वैल्यू स्टोर करने के लिए कुछ मेमोरी रिज़र्व होती है. आम तौर पर, सिर्फ़ ऐरे और स्ट्रिंग का साइज़ बहुत गहरा हो सकता है. हालांकि, स्ट्रिंग और बाहरी अरे की मुख्य मेमोरी अक्सर रेंडरर मेमोरी में होती है, जो JavaScript हीप पर सिर्फ़ एक छोटा रैपर ऑब्जेक्ट दिखाता है.

रेंडरर मेमोरी उस प्रोसेस की सभी मेमोरी होती है जिसकी जांच किए गए पेज को रेंडर किया जाता है: नेटिव मेमोरी + पेज की JS हीप मेमोरी + पेज से शुरू किए गए सभी खास वर्कर की JS हीप मेमोरी. ऐसे में, कचरा इकट्ठा करने की अपने-आप प्रोसेस होने की वजह से, छोटी सी चीज़ भी बहुत ज़्यादा मेमोरी सेव कर सकती है, ताकि दूसरी चीज़ों को नष्ट होने से रोका जा सके.

बरकरार रखे गए साइज़

यह मेमोरी का वह साइज़ है जो ऑब्जेक्ट और उसके डिपेंडेंट ऑब्जेक्ट को मिटाने के बाद छूट जाता है. ये ऐसे ऑब्जेक्ट होते हैं जिन्हें जीसी रूट से ऐक्सेस नहीं किया जा सका.

जीसी रूट ऐसे हैंडल से बने होते हैं जो स्थानीय या ग्लोबल वर्शन में बनाए जाते हैं. ऐसा तब होता है, जब नेटिव कोड को V8 के बाहर, JavaScript ऑब्जेक्ट का रेफ़रंस दिया जाता है. ऐसे सभी हैंडल, जीसी रूट > हैंडल स्कोप और जीसी रूट > ग्लोबल हैंडल में जाकर, हीप स्नैपशॉट में देखे जा सकते हैं. ब्राउज़र को लागू करने की जानकारी दिए बिना, इस दस्तावेज़ में दिए गए हैंडल के बारे में बताना उलझन भरा हो सकता है. GC रूट और हैंडल, दोनों को लेकर आपको किसी तरह की परेशानी करने की ज़रूरत नहीं है.

ऐसे कई अंदरूनी GC रूट हैं जिनमें से ज़्यादातर लोगों की पसंद नहीं हैं. ऐप्लिकेशन के हिसाब से, इन्हें इस तरह से बनाया जाता है:

  • विंडो ग्लोबल ऑब्जेक्ट (हर iframe में). हीप स्नैपशॉट में दूरी का फ़ील्ड होता है. यह विंडो से सबसे कम समय तक डेटा को बनाए रखने वाले पाथ पर प्रॉपर्टी के रेफ़रंस की संख्या होती है.
  • दस्तावेज़ वाले डीओएम ट्री में, दस्तावेज़ को ट्रैवर्स करके ऐक्सेस किए जा सकने वाले सभी नेटिव DOM नोड शामिल हैं. ज़रूरी नहीं कि उनमें से सभी में JS रैपर हों, लेकिन अगर उनके रैपर हों, तो दस्तावेज़ के लाइव होने के दौरान वे मान्य रहेंगे.
  • कभी-कभी डीबगर के कॉन्टेक्स्ट और DevTools कंसोल की मदद से ऑब्जेक्ट सेव हो सकते हैं. उदाहरण के लिए, कंसोल का आकलन करने के बाद. साफ़ कंसोल और डीबगर में कोई सक्रिय ब्रेकपॉइंट नहीं की मदद से हीप स्नैपशॉट बनाएं.

मेमोरी ग्राफ़, रूट से शुरू होता है. यह रूट, ब्राउज़र का window ऑब्जेक्ट या Node.js मॉड्यूल का Global ऑब्जेक्ट हो सकता है. यह कंट्रोल नहीं किया जा सकता कि इस रूट ऑब्जेक्ट का जीसी कैसे किया जाएगा.

रूट ऑब्जेक्ट को कंट्रोल नहीं किया जा सकता

रूट से जो भी ऐक्सेस नहीं किया जा सकता उसे GC मिल जाता है.

पेड़ को बनाए रखने वाली चीज़ें

हीप, आपस में जुड़े हुए ऑब्जेक्ट का नेटवर्क होता है. गणित की दुनिया में, इस स्ट्रक्चर को ग्राफ़ या मेमोरी ग्राफ़ कहा जाता है. एज की मदद से जोड़े गए नोड से एक ग्राफ़ बनाया जाता है. दोनों के लिए लेबल दिए जाते हैं.

  • नोड (या ऑब्जेक्ट) को उस कन्स्ट्रक्टर फ़ंक्शन के नाम से लेबल किया जाता है जिसका इस्तेमाल उन्हें बनाने के लिए किया गया था.
  • एज को प्रॉपर्टी के नाम का इस्तेमाल करके लेबल किया जाता है.

हीप प्रोफ़ाइलर का इस्तेमाल करके प्रोफ़ाइल रिकॉर्ड करने का तरीका जानें. नीचे दी गई हीप प्रोफ़ाइलर रिकॉर्डिंग में, ध्यान खींचने वाली कुछ चीज़ों में शामिल हैं: दूरी: GC रूट से दूरी. अगर एक ही तरह के करीब-करीब सभी ऑब्जेक्ट एक ही दूरी पर हैं और कुछ काफ़ी ज़्यादा दूरी पर हैं, तो पता करना फ़ायदेमंद होगा.

रूट से दूरी

डॉमिनेटर

डॉमिनेटर ऑब्जेक्ट में ट्री संरचना होती है, क्योंकि हर ऑब्जेक्ट का सिर्फ़ एक डॉमिनेटर होता है. किसी ऑब्जेक्ट के डॉमिनेटर में शायद उस ऑब्जेक्ट का सीधे तौर पर रेफ़रंस न हो जो उस ऑब्जेक्ट पर लागू होता है जो अहम है. इसका मतलब है कि डॉमिनेटर का ट्री, ग्राफ़ का स्पैनिंग ट्री नहीं है.

नीचे दिए गए डायग्राम में:

  • नोड 1, नोड 2 पर असर डाल रहा है
  • नोड 2 नोड 3, 4 और 6 पर प्रभावी हो जाता है
  • नोड 3, नोड 5 पर छा जाता है
  • नोड 5 नोड 8 पर हावी हो जाता है
  • नोड 6, नोड 7 पर असर डाल रहा है

डॉमिनेटर ट्री की संरचना

नीचे दिए गए उदाहरण में, नोड #3, #10 का डॉमिनेटर है, लेकिन #7 भी GC से #10 तक के हर आसान पाथ में मौजूद है. इसलिए, अगर B, रूट से ऑब्जेक्ट A तक के हर आसान पाथ में मौजूद है, तो ऑब्जेक्ट B को ऑब्जेक्ट A का डॉमिनेटर माना जाता है.

ऐनिमेशन वाले डोमिनेटर की इमेज

V8 की खास बातें

मेमोरी को प्रोफ़ाइल करते समय, यह समझना मददगार होता है कि हीप स्नैपशॉट एक खास तरह के क्यों दिखते हैं. इस सेक्शन में, मेमोरी से जुड़े कुछ विषयों के बारे में बताया गया है. ये विषय खास तौर पर, V8 JavaScript वर्चुअल मशीन (V8 VM या VM) से जुड़े हैं.

JavaScript ऑब्जेक्ट दिखाना

प्रिमिटिव तीन तरह के होते हैं:

  • नंबर (जैसे, 3.14159..)
  • बूलियन (सही या गलत)
  • स्ट्रिंग (जैसे, 'वर्नर हाइज़ेनबर्ग')

वे अन्य वैल्यू का रेफ़रंस नहीं दे सकते हैं और हमेशा लीफ़ या खत्म होने वाले नोड होते हैं.

नंबर इनमें से किसी एक के तौर पर सेव किए जा सकते हैं:

  • तुरंत एक 31-बिट की पूर्णांक वैल्यू, जिसे छोटे पूर्णांक (एसएमआई) कहा जाता है या
  • हीप ऑब्जेक्ट को हीप नंबर कहते हैं. हीप नंबर का इस्तेमाल उन वैल्यू को सेव करने के लिए किया जाता है जो एसएमआई फ़ॉर्म में फ़िट नहीं होती हैं, जैसे कि डबल या जब किसी वैल्यू को बॉक्स करने की ज़रूरत होती है, जैसे कि उस पर प्रॉपर्टी सेट करना.

स्ट्रिंग को इनमें से किसी एक जगह पर सेव किया जा सकता है:

  • वीएम हीप या
  • को रेंडरर की मेमोरी में सेव कर सकें. बाहरी स्टोरेज को ऐक्सेस करने के लिए, एक रैपर ऑब्जेक्ट बनाया और इस्तेमाल किया जाता है. उदाहरण के लिए, यहां वीएम हीप पर कॉपी करने के बजाय, वेब से मिलने वाले स्क्रिप्ट सोर्स और अन्य कॉन्टेंट को स्टोर किया जाता है.

नए JavaScript ऑब्जेक्ट के लिए मेमोरी, एक खास JavaScript हीप (या वीएम हीप) से तय की जाती है. इन ऑब्जेक्ट को V8 के ट्रैश कलेक्टर मैनेज करता है. इसलिए, ये तब तक ज़िंदा रहेंगे, जब तक इनके बारे में कम से कम एक मज़बूत जानकारी मौजूद होगी.

नेटिव ऑब्जेक्ट बाकी सब कुछ हैं जो JavaScript हीप में नहीं हैं. नेटिव ऑब्जेक्ट, हीप ऑब्जेक्ट के उलट है. इस ऑब्जेक्ट को V8 गार्बेज कलेक्टर, पूरे जीवनकाल में मैनेज नहीं करता. इसे सिर्फ़ JavaScript रैपर ऑब्जेक्ट का इस्तेमाल करके, JavaScript से ऐक्सेस किया जा सकता है.

कॉन्स स्ट्रिंग एक ऐसा ऑब्जेक्ट है जिसमें स्ट्रिंग के जोड़े होते हैं और फिर उन्हें जोड़कर जोड़ा जाता है. यह स्ट्रिंग जोड़ने की प्रोसेस का नतीजा होती है. नुकसान स्ट्रिंग कॉन्टेंट को जोड़ना सिर्फ़ ज़रूरत के हिसाब से होता है. इसका एक उदाहरण यह होगा कि जोड़ी गई स्ट्रिंग की सबस्ट्रिंग बनाने की ज़रूरत हो.

उदाहरण के लिए, अगर a और b को जोड़ा जाता है, तो आपको एक स्ट्रिंग (a, b) मिलती है जो स्ट्रिंग जोड़ने की प्रोसेस का नतीजा दिखाती है. अगर बाद में इस नतीजे के साथ d को जोड़ा जाता है, तो आपको एक और कॉन्फ़िगरेशन (a, b), d मिलती है.

सरणियां - अरे, संख्या वाली कुंजियों वाला ऑब्जेक्ट है. ज़्यादा डेटा स्टोर करने के लिए, V8 वीएम में इनका काफ़ी इस्तेमाल किया जाता है. डिक्शनरी की तरह इस्तेमाल किए जाने वाले की-वैल्यू पेयर के सेट का बैक अप, कलेक्शन की मदद से लिया जाता है.

सामान्य JavaScript ऑब्जेक्ट, स्टोर करने के लिए इस्तेमाल किए जाने वाले दो तरह के कलेक्शन में से एक हो सकता है:

  • नाम वाली प्रॉपर्टी और
  • संख्या वाले एलिमेंट

बहुत कम प्रॉपर्टी होने पर, उन्हें JavaScript ऑब्जेक्ट में ही अंदरूनी तौर पर सेव किया जा सकता है.

मैप करें-वह ऑब्जेक्ट जो ऑब्जेक्ट के टाइप और उसके लेआउट के बारे में बताता है. उदाहरण के लिए, मैप का इस्तेमाल प्रॉपर्टी को तेज़ी से ऐक्सेस करने के लिए, इंप्लिसिट ऑब्जेक्ट हैरारकी के बारे में बताने के लिए किया जाता है.

ऑब्जेक्ट के ग्रुप

हर नेटिव ऑब्जेक्ट ग्रुप ऐसे ऑब्जेक्ट से बना होता है जिनमें एक-दूसरे के रेफ़रंस होते हैं. उदाहरण के लिए, एक डीओएम सबट्री पर ध्यान दें, जहां हर नोड के पैरंट का लिंक होता है और अगले चाइल्ड और सिबलिंग से लिंक होता है. इस तरह, कनेक्ट किया गया ग्राफ़ बनाया जाता है. ध्यान रखें कि नेटिव ऑब्जेक्ट, JavaScript के हीप में नहीं दिखाए जाते हैं. इसलिए, उनका साइज़ शून्य है. इसके बजाय, रैपर ऑब्जेक्ट बनाए जाते हैं.

हर रैपर ऑब्जेक्ट में कमांड को रीडायरेक्ट करने के लिए, उससे जुड़े नेटिव ऑब्जेक्ट का रेफ़रंस होता है. अपने बदले में, एक ऑब्जेक्ट ग्रुप में रैपर ऑब्जेक्ट होते हैं. हालांकि, इससे ऐसा साइकल नहीं बनता है जिसे इकट्ठा न किया जा सके. इसकी वजह यह है कि जीसी उतने ही स्मार्ट तरीके से ऑब्जेक्ट के ग्रुप को रिलीज़ कर सकता है जिनके रैपर अब रेफ़रंस नहीं दिए जाते. हालांकि, एक रैपर को हटाना भूल जाने से, पूरे ग्रुप और उससे जुड़े रैपर को एक साथ होल्ड कर दिया जाएगा.