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

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

खास जानकारी

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

खास जानकारी

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • मेमोरी फ़ुटप्रिंट कॉलम, ओएस मेमोरी दिखाता है. डीओएम नोड, ओएस मेमोरी में सेव किए जाते हैं. अगर यह वैल्यू बढ़ रही है, तो इसका मतलब है कि DOM नोड बन रहे हैं.
  • 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 हज़ार div नोड जोड़ दिए जाते हैं. साथ ही, x कलेक्शन में एक लाख x वर्णों की एक स्ट्रिंग जोड़ दी जाती है. इस कोड को चलाने पर, नीचे दिए गए स्क्रीनशॉट जैसी टाइमलाइन रिकॉर्डिंग बनती है:

वृद्धि का एक आसान उदाहरण.

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

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

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

किसी DOM नोड को सिर्फ़ तब ग़ैर-ज़रूरी डेटा के तौर पर हटाया जा सकता है, जब पेज के DOM ट्री या JavaScript कोड में उसका कोई रेफ़रंस न हो. जब किसी नोड को DOM ट्री से हटा दिया जाता है, लेकिन कुछ 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);

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

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

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

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

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

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

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

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

पेड़ के गिरने की जांच करना.

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

अलग किए गए नोड की जांच करना.

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

ऐलोकेशन टाइमलाइन एक और टूल है. इसकी मदद से, JS ढेर में मेमोरी लीक का पता लगाया जा सकता है.

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

var x = [];

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

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

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

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

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

परफ़ॉर्मेंस टाइमलाइन में नए ऐलोकेशन.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

अक्सर कचरा इकट्ठा करने की जगहें

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

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

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