मेमोरी से जुड़ी समस्याएं ठीक करना

Kayce Basques
Kayce Basques

Chrome और DevTools का इस्तेमाल करके, मेमोरी से जुड़ी उन समस्याओं का पता लगाने का तरीका जानें जिनसे पेज की परफ़ॉर्मेंस पर असर पड़ता है. इनमें मेमोरी लीक, मेमोरी ब्लोट, और बार-बार होने वाले गार्बेज कलेक्शन शामिल हैं.

खास जानकारी

  • Chrome टास्क मैनेजर की मदद से, यह पता लगाएं कि आपका पेज कितनी मेमोरी इस्तेमाल कर रहा है.
  • टाइमलाइन रिकॉर्डिंग की मदद से, समय के साथ मेमोरी के इस्तेमाल को विज़ुअलाइज़ करें.
  • हीप स्नैपशॉट की मदद से, डिटैच किए गए डीओएम ट्री की पहचान करें. यह मेमोरी लीक होने की एक आम वजह है.
  • एलोकेशन टाइमलाइन रिकॉर्डिंग की मदद से, यह पता लगाएं कि आपके JS हीप में नई मेमोरी कब असाइन की जा रही है.
  • JavaScript रेफ़रंस से रिटेन किए गए, अलग किए गए एलिमेंट की पहचान करना.

खास जानकारी

RAIL परफ़ॉर्मेंस मॉडल के मुताबिक, आपकी परफ़ॉर्मेंस से जुड़ी कोशिशों का फ़ोकस आपके उपयोगकर्ता होने चाहिए.

मेमोरी से जुड़ी समस्याएं अहम होती हैं, क्योंकि अक्सर उपयोगकर्ताओं को इनका पता चल जाता है. उपयोगकर्ताओं को मेमोरी से जुड़ी समस्याएं इन तरीकों से दिख सकती हैं:

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

मेमोरी ब्लोट: "बहुत ज़्यादा" कितना होता है?

मेमोरी लीक को आसानी से समझा जा सकता है. अगर कोई साइट लगातार ज़्यादा से ज़्यादा मेमोरी का इस्तेमाल कर रही है, तो इसका मतलब है कि मेमोरी लीक हो रही है. हालांकि, मेमोरी ब्लोट को कम करना थोड़ा मुश्किल होता है. "बहुत ज़्यादा मेमोरी का इस्तेमाल" करने का क्या मतलब है?

इसके लिए कोई तय संख्या नहीं है, क्योंकि अलग-अलग डिवाइसों और ब्राउज़र की क्षमताएं अलग-अलग होती हैं. जो पेज हाई-एंड स्मार्टफ़ोन पर आसानी से चलता है वह लो-एंड स्मार्टफ़ोन पर क्रैश हो सकता है.

इसके लिए, RAIL मॉडल का इस्तेमाल करें और अपने उपयोगकर्ताओं पर फ़ोकस करें. यह पता लगाएं कि आपके उपयोगकर्ता किन डिवाइसों का ज़्यादा इस्तेमाल करते हैं. इसके बाद, उन डिवाइसों पर अपने पेज की जांच करें. अगर पेज की परफ़ॉर्मेंस लगातार खराब रहती है, तो हो सकता है कि पेज उन डिवाइसों की मेमोरी क्षमता से ज़्यादा मेमोरी का इस्तेमाल कर रहा हो.

Chrome टास्क मैनेजर की मदद से, रीयल टाइम में मेमोरी के इस्तेमाल पर नज़र रखना

मेमोरी से जुड़ी समस्या की जांच करने के लिए, Chrome टास्क मैनेजर का इस्तेमाल करें. टास्क मैनेजर, रीयल-टाइम में मॉनिटर करने की सुविधा है. इससे आपको पता चलता है कि कोई पेज कितनी मेमोरी इस्तेमाल कर रहा है.

  1. टास्क मैनेजर खोलने के लिए, Shift+Esc दबाएं या Chrome के मुख्य मेन्यू में जाकर, ज़्यादा टूल > टास्क मैनेजर को चुनें.

    टास्क मैनेजर खोला जा रहा है.

  2. टास्क मैनेजर के टेबल हेडर पर राइट क्लिक करें और JavaScript मेमोरी को चालू करें.

    टास्क मैनेजर हेडर में जेएस मेमोरी को चालू किया जा रहा है.

इन दोनों कॉलम से आपको यह पता चलता है कि आपका पेज मेमोरी का इस्तेमाल कैसे कर रहा है:

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

    JavaScript मेमोरी हेडर की सुविधा चालू होने पर, Task Manager.

परफ़ॉर्मेंस रिकॉर्डिंग की मदद से, मेमोरी लीक को विज़ुअलाइज़ करना

जांच शुरू करने के लिए, परफ़ॉर्मेंस पैनल का भी इस्तेमाल किया जा सकता है. परफ़ॉर्मेंस पैनल की मदद से, समय के साथ किसी पेज के मेमोरी इस्तेमाल को विज़ुअलाइज़ किया जा सकता है.

  1. DevTools में परफ़ॉर्मेंस पैनल खोलें.
  2. मेमोरी चेकबॉक्स को चुनें.
  3. रिकॉर्डिंग करना.

परफ़ॉर्मेंस मेमोरी रिकॉर्डिंग दिखाने के लिए, यहां दिया गया कोड देखें:

var x = [];

function grow() {
  for (var i = 0; i < 10000; i++) {
    document.body.appendChild(document.createElement('div'));
  }
  x.push(new Array(1000000).join('x'));
}

document.getElementById('grow').addEventListener('click', grow);

कोड में रेफ़रंस के तौर पर दिए गए बटन को हर बार दबाने पर, दस्तावेज़ के मुख्य हिस्से में 10,000 div नोड जोड़ दिए जाते हैं. साथ ही, x अरे में 10 लाख x वर्णों की एक स्ट्रिंग जोड़ दी जाती है. इस कोड को चलाने पर, टाइमलाइन रिकॉर्डिंग जनरेट होती है. जैसे, यहां दिए गए स्क्रीनशॉट में:

बढ़ोतरी का एक आसान उदाहरण.

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

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

हीप स्नैपशॉट की मदद से, डीओएम ट्री से अलग किए गए मेमोरी लीक का पता लगाना

किसी डीओएम नोड को सिर्फ़ तब गार्बेज कलेक्ट किया जा सकता है, जब पेज के डीओएम ट्री या JavaScript कोड में उसका कोई रेफ़रंस न हो. किसी नोड को तब "अलग किया गया" कहा जाता है, जब उसे डीओएम ट्री से हटा दिया जाता है, लेकिन कुछ JavaScript अब भी उसे रेफ़रंस के तौर पर इस्तेमाल करते हैं. डिटैच किए गए डीओएम नोड, मेमोरी लीक की एक सामान्य वजह हैं. इस सेक्शन में, DevTools के हीप प्रोफ़ाइलर का इस्तेमाल करके, अलग किए गए नोड की पहचान करने का तरीका बताया गया है.

यहां अलग किए गए डीओएम नोड का एक आसान उदाहरण दिया गया है.

var detachedTree;

function create() {
  var ul = document.createElement('ul');
  for (var i = 0; i < 10; i++) {
    var li = document.createElement('li');
    ul.appendChild(li);
  }
  detachedTree = ul;
}

document.getElementById('create').addEventListener('click', create);

कोड में दिए गए बटन पर क्लिक करने से, 10 li चाइल्ड एलिमेंट वाला एक ul नोड बनता है. कोड में इन नोड का रेफ़रंस दिया गया है, लेकिन ये डीओएम ट्री में मौजूद नहीं हैं. इसलिए, ये अलग हो गए हैं.

हीप स्नैपशॉट, डिटैच किए गए नोड की पहचान करने का एक तरीका है. जैसा कि नाम से पता चलता है, हीप स्नैपशॉट से आपको पता चलता है कि स्नैपशॉट के समय, आपके पेज के JS ऑब्जेक्ट और DOM नोड के बीच मेमोरी कैसे डिस्ट्रिब्यूट की जाती है.

स्नैपशॉट बनाने के लिए, DevTools खोलें और मेमोरी पैनल पर जाएं. इसके बाद, हीप स्नैपशॉट रेडियो बटन को चुनें और फिर स्नैपशॉट लें बटन को दबाएं.

'हीप स्नैपशॉट लें' रेडियो बटन चुना गया.

स्नैपशॉट को प्रोसेस होने और लोड होने में कुछ समय लग सकता है. प्रोसेस पूरी होने के बाद, बाईं ओर मौजूद पैनल (इसका नाम Heap snapshots है) से इसे चुनें.

अलग किए गए डीओएम ट्री खोजने के लिए, क्लास फ़िल्टर इनपुट बॉक्स में Detached टाइप करें.

डिटैच किए गए नोड के लिए फ़िल्टर करना.

अलग किए गए ट्री की जांच करने के लिए, कैरेट को बड़ा करें.

अलग किए गए ट्री की जांच करना.

किसी नोड की ज़्यादा जांच करने के लिए, उस पर क्लिक करें. ऑब्जेक्ट पैनल में, आपको उस कोड के बारे में ज़्यादा जानकारी दिख सकती है जो इसे रेफ़र कर रहा है. उदाहरण के लिए, यहां दिए गए स्क्रीनशॉट में देखा जा सकता है कि detachedTree वैरिएबल, नोड को रेफ़र कर रहा है. इस मेमोरी लीक को ठीक करने के लिए, आपको उस कोड को देखना होगा जो detachedTree का इस्तेमाल करता है. साथ ही, यह पक्का करना होगा कि ज़रूरत न होने पर, वह नोड के रेफ़रंस को हटा दे.

डिटैच किए गए नोड की जांच करना.

ऐलोकेशन टाइमलाइन की मदद से, JS हीप मेमोरी लीक की पहचान करना

एलोकेशन टाइमलाइन एक अन्य टूल है. इसकी मदद से, अपने JS हीप में मेमोरी लीक को ट्रैक किया जा सकता है.

ऐलोकेशन टाइमलाइन को दिखाने के लिए, यहां दिया गया कोड देखें:

var x = [];

function grow() {
  x.push(new Array(1000000).join('x'));
}

document.getElementById('grow').addEventListener('click', grow);

कोड में रेफ़रंस के तौर पर दिए गए बटन को हर बार दबाने पर, x कलेक्शन में 10 लाख वर्णों की एक स्ट्रिंग जुड़ जाती है.

एलोकेशन टाइमलाइन रिकॉर्ड करने के लिए, DevTools खोलें और मेमोरी पैनल पर जाएं. इसके बाद, टाइमलाइन पर एलोकेशन रेडियो बटन को चुनें और रिकॉर्ड करें बटन को दबाएं. अब वह कार्रवाई करें जिससे आपको लगता है कि मेमोरी लीक हो रही है. इसके बाद, काम पूरा होने पर रिकॉर्डिंग बंद करें बटन को दबाएं.

रिकॉर्डिंग के दौरान, देखें कि एलोकेशन टाइमलाइन पर कोई नीला बार दिख रहा है या नहीं. जैसे, यहां दिए गए स्क्रीनशॉट में दिख रहा है.

परफ़ॉर्मेंस टाइमलाइन में नए आवंटन.

ये नीले बार, मेमोरी के नए बंटवारे को दिखाते हैं. मेमोरी के ये नए बंटवारे, मेमोरी लीक के लिए ज़िम्मेदार हो सकते हैं. किसी बार को ज़ूम करके, कंस्ट्रक्टर पैनल को फ़िल्टर किया जा सकता है. इससे सिर्फ़ वे ऑब्जेक्ट दिखेंगे जिन्हें तय की गई समयावधि के दौरान असाइन किया गया था.

ज़ूम की गई बजट टाइमलाइन.

ऑब्जेक्ट को बड़ा करें और उसकी वैल्यू पर क्लिक करें. इससे आपको ऑब्जेक्ट पैनल में उसके बारे में ज़्यादा जानकारी दिखेगी. उदाहरण के लिए, नीचे दिए गए स्क्रीनशॉट में, नए ऑब्जेक्ट की जानकारी देखकर, आपको पता चलेगा कि इसे Window स्कोप में x वैरिएबल को असाइन किया गया था.

स्ट्रिंग अरे के ऑब्जेक्ट की जानकारी.

फ़ंक्शन के हिसाब से मेमोरी के बंटवारे की जांच करना

JavaScript फ़ंक्शन के हिसाब से मेमोरी के बंटवारे का डेटा देखने के लिए, मेमोरी पैनल में एलोकेशन सैंपलिंग प्रोफ़ाइल टाइप का इस्तेमाल करें.

मेमोरी पैनल में, ऐलोकेशन सैंपलिंग प्रोफ़ाइलर.

  1. एलोकेशन सैंपलिंग रेडियो बटन को चुनें. अगर पेज पर कोई वर्कर है, तो उसे JavaScript वीएम इंस्टेंस चुनें विंडो से प्रोफ़ाइलिंग टारगेट के तौर पर चुना जा सकता है.
  2. शुरू करें बटन दबाएं.
  3. पेज पर वे कार्रवाइयां करें जिनकी आपको जांच करनी है.
  4. सभी कार्रवाइयां पूरी करने के बाद, बंद करें बटन दबाएं.

DevTools, आपको फ़ंक्शन के हिसाब से मेमोरी के बंटवारे की जानकारी दिखाता है. डिफ़ॉल्ट व्यू हैवी (बॉटम अप) होता है. इसमें सबसे ज़्यादा मेमोरी का इस्तेमाल करने वाले फ़ंक्शन सबसे ऊपर दिखते हैं.

एलोकेशन प्रोफ़ाइल के नतीजों वाला पेज.

JS के रेफ़रंस से रिटेन किए गए ऑब्जेक्ट की पहचान करना

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

एचटीएमएल नोड और नोड की संख्या देखने के लिए, डिटैच किए गए एलिमेंट की प्रोफ़ाइल रिकॉर्ड करें.

अलग किए गए एलिमेंट की प्रोफ़ाइल का उदाहरण.

बार-बार होने वाले गारबेज कलेक्शन का पता लगाना

अगर आपका पेज बार-बार रुकता है, तो हो सकता है कि आपको गार्बेज कलेक्शन से जुड़ी समस्याएं आ रही हों.

बार-बार होने वाले गार्बेज कलेक्शन का पता लगाने के लिए, Chrome टास्क मैनेजर या टाइमलाइन मेमोरी रिकॉर्डिंग का इस्तेमाल किया जा सकता है. टास्क मैनेजर में, मेमोरी या JavaScript मेमोरी की वैल्यू में बार-बार होने वाले उतार-चढ़ाव से, बार-बार होने वाले गार्बेज कलेक्शन का पता चलता है. टाइमलाइन रिकॉर्डिंग में, JS हीप या नोड काउंट ग्राफ़ का बार-बार बढ़ना और घटना, बार-बार गार्बेज कलेक्शन होने का संकेत देता है.

समस्या का पता चलने के बाद, ऐलोकेशन टाइमलाइन रिकॉर्डिंग का इस्तेमाल करके यह पता लगाया जा सकता है कि मेमोरी कहां ऐलोकेट की जा रही है और किन फ़ंक्शन की वजह से ऐलोकेशन हो रहे हैं.