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

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

ब्रेंडन केनी
ब्रेंडन कैनी
उलान डेगेनबेव
उलान डिजेनबेव

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

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

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 API से किस तरह अलग है?

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

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

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

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

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

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

ब्राउज़र सहायता

  • 89
  • 89
  • x
  • x

सोर्स

फ़िलहाल, यह एपीआई सिर्फ़ Chromium 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 सेकंड पर सेट है. हालांकि, ऐसा पहले भी हो सकता है. Chrome को --enable-blink-features='ForceEagerMeasureMemory' कमांड लाइन फ़्लैग के साथ शुरू करने से, टाइम आउट की अवधि शून्य हो जाती है. इससे लोकल डीबगिंग और टेस्टिंग में मदद मिलती है.

उदाहरण

एपीआई का इस्तेमाल करने का सुझाव, ग्लोबल मेमोरी मॉनिटर तय करने के लिए किया जाता है, जो पूरे वेब पेज की मेमोरी के इस्तेमाल का सैंपल देता है. साथ ही, एग्रीगेशन और विश्लेषण के लिए नतीजों को सर्वर पर भेजता है. सबसे आसान तरीका है, समय-समय पर सैंपल लेना. उदाहरण के लिए, हर 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 और DOM मेमोरी शामिल हैं.

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

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

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

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

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

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

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

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

सहायता करें

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

मददगार लिंक

स्वीकार हैं

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

Unsplash पर हैरिसन ब्रॉडबेंट की हीरो इमेज