measureUserAgentspecificMemory() की मदद से, अपने वेब पेज के कुल मेमोरी इस्तेमाल पर नज़र रखें

रिग्रेशन का पता लगाने के लिए, प्रोडक्शन में अपने वेब पेज की मेमोरी के इस्तेमाल को मेज़र करने का तरीका जानें.

Brendan Kenny
Brendan Kenny
Ulan Degenbaev
Ulan Degenbaev

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

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

const object = {a: new Array(1000), b: new Array(2000)};
setInterval(() => console.log(object.a), 1000);

यहां बड़े कलेक्शन b की अब ज़रूरत नहीं है. हालांकि, ब्राउज़र इसे वापस नहीं लेता, क्योंकि कॉलबैक में object.b के ज़रिए अब भी इसे ऐक्सेस किया जा सकता है. इस वजह से, बड़े ऐरे की मेमोरी लीक हो जाती है.

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

इस समस्या को हल करने के लिए, सबसे पहले इसे मेज़र करना ज़रूरी है. नए performance.measureUserAgentSpecificMemory() एपीआई की मदद से, डेवलपर प्रोडक्शन में अपने वेब पेजों की मेमोरी के इस्तेमाल को मेज़र कर सकते हैं. इससे, लोकल टेस्टिंग के दौरान छूट जाने वाले मेमोरी लीक का पता लगाया जा सकता है.

performance.measureUserAgentSpecificMemory(), लेगसी performance.memory एपीआई से किस तरह अलग है?

अगर आपको मौजूदा नॉन-स्टैंडर्ड performance.memory एपीआई के बारे में जानकारी है, तो हो सकता है कि आप यह जानना चाहें कि नया एपीआई इससे किस तरह अलग है. मुख्य अंतर यह है कि पुराना एपीआई, JavaScript हीप का साइज़ दिखाता है. वहीं, नया एपीआई, वेब पेज से इस्तेमाल की गई मेमोरी का अनुमान लगाता है. यह अंतर तब अहम हो जाता है, जब Chrome एक ही हीप को कई वेब पेजों या एक ही वेब पेज के कई इंस्टेंस के साथ शेयर करता है. ऐसे मामलों में, पुराने एपीआई का नतीजा मनमाने तरीके से गलत हो सकता है. पुराने एपीआई को "हीप" जैसे लागू करने से जुड़ी खास शर्तों के हिसाब से तय किया जाता है. इसलिए, इसे स्टैंडर्ड बनाना नामुमकिन है.

एक और अंतर यह है कि नया एपीआई, गार्बेज कलेक्शन के दौरान मेमोरी मेज़रमेंट करता है. इससे नतीजों में ग़ैर-ज़रूरी जानकारी कम हो जाती है. हालांकि, नतीजे जनरेट होने में कुछ समय लग सकता है. ध्यान दें कि अन्य ब्राउज़र, गार्बेज कलेक्शन पर निर्भर हुए बिना नए एपीआई को लागू करने का फ़ैसला ले सकते हैं.

इस्तेमाल के सुझाए गए उदाहरण

किसी वेब पेज की मेमोरी का इस्तेमाल, इवेंट के समय, उपयोगकर्ता की कार्रवाइयों, और गारबेज कलेक्शन पर निर्भर करता है. इसलिए, मेमोरी मेज़रमेंट एपीआई का मकसद, प्रोडक्शन से मेमोरी के इस्तेमाल का डेटा इकट्ठा करना है. अलग-अलग कॉल के नतीजे कम उपयोगी होते हैं. इस्तेमाल के उदाहरण:

  • वेब पेज का नया वर्शन रोल आउट करते समय, रिग्रेशन का पता लगाना, ताकि नई मेमोरी लीक का पता लगाया जा सके.
  • किसी नई सुविधा की A/B टेस्टिंग करना, ताकि यह पता लगाया जा सके कि वह मेमोरी पर कितना असर डालती है और मेमोरी लीक का पता लगाया जा सके.
  • मेमोरी लीक की मौजूदगी या अनुपस्थिति की पुष्टि करने के लिए, मेमोरी के इस्तेमाल को सेशन कितनी देर चला, इसके साथ कोरिलेट करना.
  • मेमोरी के इस्तेमाल को उपयोगकर्ता मेट्रिक के साथ जोड़कर, मेमोरी के इस्तेमाल के असर को पूरी तरह से समझना.

वेबसाइट का अलग-अलग ब्राउज़र पर चलना

Browser Support

  • Chrome: 89.
  • Edge: 89.
  • Firefox: not supported.
  • Safari: not supported.

Source

फ़िलहाल, यह एपीआई सिर्फ़ Chromium पर आधारित ब्राउज़र में काम करता है. इसकी शुरुआत Chrome 89 से हुई है. एपीआई का नतीजा, लागू करने के तरीके पर काफ़ी निर्भर करता है. इसकी वजह यह है कि ब्राउज़र में, मेमोरी में ऑब्जेक्ट को दिखाने और मेमोरी के इस्तेमाल का अनुमान लगाने के अलग-अलग तरीके होते हैं. अगर मेमोरी के सही इस्तेमाल का हिसाब लगाना बहुत महंगा या मुश्किल है, तो ब्राउज़र कुछ मेमोरी क्षेत्रों को हिसाब से बाहर रख सकते हैं. इसलिए, अलग-अलग ब्राउज़र के नतीजों की तुलना नहीं की जा सकती. एक ही ब्राउज़र के नतीजों की तुलना करना ही सही होता है.

performance.measureUserAgentSpecificMemory() का इस्तेमाल करना

सुविधा का पता लगाने की सुविधा

अगर एक्ज़ीक्यूशन एनवायरमेंट, क्रॉस-ऑरिजिन जानकारी लीक होने से रोकने के लिए सुरक्षा से जुड़ी ज़रूरी शर्तों को पूरा नहीं करता है, तो performance.measureUserAgentSpecificMemory फ़ंक्शन उपलब्ध नहीं होगा या SecurityError के साथ काम नहीं करेगा. यह क्रॉस-ऑरिजिन आइसोलेशन पर निर्भर करता है. इसे कोई वेब पेज, COOP+COEP हेडर सेट करके चालू कर सकता है.

रनटाइम के दौरान, यह पता लगाया जा सकता है कि डिवाइस पर यह सुविधा काम करती है या नहीं:

if (!window.crossOriginIsolated) {
  console.log('performance.measureUserAgentSpecificMemory() is only available in cross-origin-isolated pages');
} else if (!performance.measureUserAgentSpecificMemory) {
  console.log('performance.measureUserAgentSpecificMemory() is not available in this browser');
} else {
  let result;
  try {
    result = await performance.measureUserAgentSpecificMemory();
  } catch (error) {
    if (error instanceof DOMException && error.name === 'SecurityError') {
      console.log('The context is not secure.');
    } else {
      throw error;
    }
  }
  console.log(result);
}

लोकल टेस्टिंग

Chrome, गार्बेज कलेक्शन के दौरान मेमोरी का आकलन करता है. इसका मतलब है कि एपीआई, नतीजे के प्रॉमिस को तुरंत रिज़ॉल्व नहीं करता. इसके बजाय, वह अगले गार्बेज कलेक्शन का इंतज़ार करता है.

एपीआई को कॉल करने पर, कुछ समय बाद गार्बेज कलेक्शन होता है. फ़िलहाल, यह समय 20 सेकंड पर सेट है. हालांकि, यह इससे पहले भी हो सकता है. --enable-blink-features='ForceEagerMeasureMemory' कमांड-लाइन फ़्लैग के साथ Chrome को शुरू करने से, टाइम आउट की अवधि शून्य हो जाती है. यह स्थानीय तौर पर डीबग करने और टेस्टिंग के लिए मददगार होता है.

उदाहरण

एपीआई का इस्तेमाल करने का सुझाव दिया जाता है, ताकि एक ग्लोबल मेमोरी मॉनिटर तय किया जा सके. यह मॉनिटर, पूरे वेब पेज की मेमोरी के इस्तेमाल का सैंपल लेता है और नतीजों को एग्रीगेशन और विश्लेषण के लिए सर्वर पर भेजता है. इसका सबसे आसान तरीका है कि समय-समय पर सैंपल लिया जाए. उदाहरण के लिए, हर M मिनट में. हालांकि, इससे डेटा में गड़बड़ी हो सकती है, क्योंकि सैंपल के बीच में मेमोरी पीक हो सकती है.

यहां दिए गए उदाहरण में, पॉइसन प्रोसेस का इस्तेमाल करके, मेमोरी के इस्तेमाल को बिना किसी पक्षपात के मेज़र करने का तरीका बताया गया है. इससे यह गारंटी मिलती है कि सैंपल किसी भी समय पर बराबर संभावना के साथ हो सकते हैं.

सबसे पहले, एक ऐसा फ़ंक्शन तय करें जो रैंडम इंटरवल के साथ setTimeout() का इस्तेमाल करके, मेमोरी के अगले मेज़रमेंट को शेड्यूल करे.

function scheduleMeasurement() {
  // Check measurement API is available.
  if (!window.crossOriginIsolated) {
    console.log('performance.measureUserAgentSpecificMemory() is only available in cross-origin-isolated pages');
    console.log('See https://web.dev/coop-coep/ to learn more')
    return;
  }
  if (!performance.measureUserAgentSpecificMemory) {
    console.log('performance.measureUserAgentSpecificMemory() is not available in this browser');
    return;
  }
  const interval = measurementInterval();
  console.log(`Running next memory measurement in ${Math.round(interval / 1000)} seconds`);
  setTimeout(performMeasurement, interval);
}

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

function measurementInterval() {
  const MEAN_INTERVAL_IN_MS = 5 * 60 * 1000;
  return -Math.log(Math.random()) * MEAN_INTERVAL_IN_MS;
}

आखिर में, एसिंक performMeasurement() फ़ंक्शन, एपीआई को शुरू करता है, नतीजे को रिकॉर्ड करता है, और अगले मेज़रमेंट को शेड्यूल करता है.

async function performMeasurement() {
  // 1. Invoke performance.measureUserAgentSpecificMemory().
  let result;
  try {
    result = await performance.measureUserAgentSpecificMemory();
  } catch (error) {
    if (error instanceof DOMException && error.name === 'SecurityError') {
      console.log('The context is not secure.');
      return;
    }
    // Rethrow other errors.
    throw error;
  }
  // 2. Record the result.
  console.log('Memory usage:', result);
  // 3. Schedule the next measurement.
  scheduleMeasurement();
}

आखिर में, तापमान मापना शुरू करें.

// Start measurements.
scheduleMeasurement();

नतीजा कुछ ऐसा दिख सकता है:

// Console output:
{
  bytes: 60_100_000,
  breakdown: [
    {
      bytes: 40_000_000,
      attribution: [{
        url: 'https://example.com/',
        scope: 'Window',
      }],
      types: ['JavaScript']
    },

    {
      bytes: 20_000_000,
      attribution: [{
          url: 'https://example.com/iframe',
          container: {
            id: 'iframe-id-attribute',
            src: '/iframe',
          },
          scope: 'Window',
      }],
      types: ['JavaScript']
    },

    {
      bytes: 100_000,
      attribution: [],
      types: ['DOM']
    },
  ],
}

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

breakdown सूची में, इस्तेमाल की गई मेमोरी के बारे में ज़्यादा जानकारी दी गई है. हर एंट्री, मेमोरी के कुछ हिस्से के बारे में बताती है. साथ ही, उसे यूआरएल से पहचानी गई विंडो, iframe, और वर्कर के सेट से जोड़ती है. types फ़ील्ड में, मेमोरी से जुड़े खास तरह के मेमोरी टाइप की सूची होती है.

यह ज़रूरी है कि सभी सूचियों को सामान्य तरीके से इस्तेमाल किया जाए. साथ ही, किसी खास ब्राउज़र के आधार पर अनुमानों को हार्डकोड न किया जाए. उदाहरण के लिए, कुछ ब्राउज़र खाली breakdown या खाली attribution दिखा सकते हैं. अन्य ब्राउज़र, attribution में कई एंट्री दिखा सकते हैं. इससे पता चलता है कि वे यह नहीं बता सकते कि इनमें से किस एंट्री के पास मेमोरी है.

सुझाव/राय दें या शिकायत करें

वेब परफ़ॉर्मेंस कम्यूनिटी ग्रुप और Chrome की टीम, performance.measureUserAgentSpecificMemory() के बारे में आपके विचार और अनुभव जानना चाहती है.

हमें एपीआई के डिज़ाइन के बारे में बताएं

क्या एपीआई में कोई ऐसी चीज़ है जो उम्मीद के मुताबिक काम नहीं करती? क्या आपके पास अपने आइडिया को लागू करने के लिए ज़रूरी प्रॉपर्टी मौजूद नहीं हैं? performance.measureUserAgentSpecificMemory() GitHub रिपॉज़िटरी पर, स्पेसिफ़िकेशन से जुड़ी समस्या की शिकायत करें या किसी मौजूदा समस्या पर अपने विचार जोड़ें.

लागू करने से जुड़ी समस्या की शिकायत करना

क्या आपको Chrome के लागू होने में कोई गड़बड़ी मिली? या फिर, लागू करने का तरीका स्पेसिफ़िकेशन से अलग है? new.crbug.com पर जाकर, गड़बड़ी की शिकायत करें. पक्का करें कि आपने ज़्यादा से ज़्यादा जानकारी दी हो. साथ ही, गड़बड़ी को फिर से ट्रिगर करने के लिए आसान निर्देश दें. इसके अलावा, कॉम्पोनेंट को Blink>PerformanceAPIs पर सेट करें.

क्रिएटर के लिए अपना सपोर्ट दिखाएं

क्या आपको performance.measureUserAgentSpecificMemory() का इस्तेमाल करना है? सार्वजनिक तौर पर आपका समर्थन मिलने से, Chrome टीम को सुविधाओं को प्राथमिकता देने में मदद मिलती है. साथ ही, ब्राउज़र उपलब्ध कराने वाली अन्य कंपनियों को यह पता चलता है कि इन सुविधाओं को उपलब्ध कराना कितना ज़रूरी है. @ChromiumDev पर ट्वीट करके हमें बताएं कि इसका इस्तेमाल कहां और कैसे किया जा रहा है.

सहायता के लिए लिंक

Acknowledgements

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