उपयोगकर्ता को ध्यान में रखकर बनाई गई मेट्रिक का इस्तेमाल करके, किसी भी वेबसाइट पर परफ़ॉर्मेंस का आकलन किया जा सकता है. इन मेट्रिक की मदद से, ये काम किए जा सकते हैं:
- जानें कि असली उपयोगकर्ताओं को वेब का इस्तेमाल करने में कैसा अनुभव मिलता है.
- अपनी साइट की तुलना किसी प्रतिस्पर्धी की साइट से करें.
- कस्टम कोड लिखे बिना, अपने ऐनलिटिक्स टूल में काम का और कार्रवाई किया जा सकने वाला डेटा ट्रैक करें.
यूनिवर्सल मेट्रिक से, परफ़ॉर्मेंस का शुरुआती आकलन किया जा सकता है. हालांकि, कई मामलों में आपको अपनी साइट की परफ़ॉर्मेंस का पूरा आकलन करने के लिए, इन मेट्रिक के अलावा ज़्यादा मेट्रिक मेज़र करनी होती हैं.
कस्टम मेट्रिक की मदद से, अपनी साइट के अनुभव के उन पहलुओं को मेज़र किया जा सकता है जो सिर्फ़ आपकी साइट पर लागू हो सकते हैं. जैसे:
- एक पेज के ऐप्लिकेशन (एसपीए) को एक "पेज" से दूसरे पेज पर ट्रांज़िशन करने में कितना समय लगता है.
- लॉग-इन किए हुए उपयोगकर्ताओं के लिए, डेटाबेस से फ़ेच किया गया डेटा दिखाने में पेज को कितना समय लगता है.
- सर्वर साइड रेंडर किए गए (एसएसआर) ऐप्लिकेशन को हाइड्रेट होने में कितना समय लगता है.
- वेबसाइट पर बार-बार आने वाले लोगों के लोड किए गए संसाधनों के लिए, कैश हिट रेट.
- गेम में क्लिक या कीबोर्ड इवेंट की लेटेन्सी.
कस्टम मेट्रिक का आकलन करने के लिए एपीआई
पहले, वेब डेवलपर के पास परफ़ॉर्मेंस का आकलन करने के लिए, बहुत कम लो-लेवल एपीआई होते थे. इसलिए, उन्हें यह पता लगाने के लिए हैक का इस्तेमाल करना पड़ता था कि कोई साइट अच्छा परफ़ॉर्म कर रही है या नहीं.
उदाहरण के लिए, requestAnimationFrame लूप चलाकर और हर फ़्रेम के बीच के अंतर का हिसाब लगाकर, यह पता लगाया जा सकता है कि लंबे समय तक चलने वाले JavaScript टास्क की वजह से मुख्य थ्रेड ब्लॉक हो गई है या नहीं. अगर डेल्टा, डिसप्ले के फ़्रेमरेट से काफ़ी ज़्यादा है, तो उसे लंबे समय तक चलने वाले टास्क के तौर पर रिपोर्ट किया जा सकता है. हालांकि, इस तरह के हैक का इस्तेमाल करने का सुझाव नहीं दिया जाता है. ऐसा इसलिए, क्योंकि इनसे परफ़ॉर्मेंस पर असर पड़ता है. उदाहरण के लिए, बैटरी खत्म हो जाती है.
परफ़ॉर्मेंस को सटीक तरीके से मेज़र करने का पहला नियम यह है कि परफ़ॉर्मेंस मेज़रमेंट की तकनीकों की वजह से, परफ़ॉर्मेंस से जुड़ी समस्याएं न आ रही हों. इसलिए, अगर हो सके, तो अपनी साइट पर मेज़र की जाने वाली किसी भी कस्टम मेट्रिक के लिए, इनमें से किसी एक एपीआई का इस्तेमाल करें.
Performance Observer API
Performance Observer API, इस पेज पर बताए गए अन्य सभी परफ़ॉर्मेंस एपीआई से डेटा इकट्ठा करता है और उसे दिखाता है. अच्छा डेटा पाने के लिए, इसे समझना ज़रूरी है.
परफ़ॉर्मेंस से जुड़े इवेंट की सूचनाएं पाने के लिए, PerformanceObserver का इस्तेमाल किया जा सकता है. इससे एपीआई कॉल बैक, निष्क्रियता की अवधि के दौरान ट्रिगर होते हैं. इसका मतलब है कि आम तौर पर, ये पेज की परफ़ॉर्मेंस में रुकावट नहीं डालते.
PerformanceObserver बनाने के लिए, इसे एक कॉलबैक पास करें. यह कॉलबैक तब चलेगा, जब नई परफ़ॉर्मेंस एंट्री भेजी जाएंगी. इसके बाद, observe() तरीके का इस्तेमाल करके, ऑब्ज़र्वर को यह बताया जाता है कि किस तरह की एंट्री को सुनना है:
const po = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// Log the entry and all associated details.
console.log(entry.toJSON());
}
});
po.observe({type: 'some-entry-type'});
यहां दिए गए सेक्शन में, परफ़ॉर्मेंस मॉनिटरिंग के लिए उपलब्ध सभी एंट्री टाइप की सूची दी गई है. हालांकि, नए ब्राउज़र में, स्टैटिक PerformanceObserver.supportedEntryTypes प्रॉपर्टी के ज़रिए यह देखा जा सकता है कि कौनसे एंट्री टाइप उपलब्ध हैं.
पहले से मौजूद एंट्री देखना
डिफ़ॉल्ट रूप से, PerformanceObserver ऑब्जेक्ट सिर्फ़ एंट्री होने पर उन्हें देख सकते हैं. अगर आपको परफ़ॉर्मेंस के आंकड़ों के कोड को लेज़ी-लोड करना है, ताकि यह ज़्यादा प्राथमिकता वाले संसाधनों को ब्लॉक न करे, तो इससे समस्याएं हो सकती हैं.
पुरानी एंट्री (हो जाने के बाद) पाने के लिए, observe() को कॉल करते समय buffered फ़्लैग को true पर सेट करें. जब आपका PerformanceObserver कॉलबैक पहली बार कॉल किया जाता है, तब ब्राउज़र अपने परफ़ॉर्मेंस एंट्री बफ़र से पुरानी एंट्री शामिल करेगा. ऐसा उस टाइप के लिए बफ़र के ज़्यादा से ज़्यादा साइज़ तक किया जाएगा.
po.observe({
type: 'some-entry-type',
buffered: true,
});
परफ़ॉर्मेंस से जुड़े पुराने एपीआई, जिनका इस्तेमाल नहीं करना चाहिए
Performance Observer API से पहले, डेवलपर performance ऑब्जेक्ट पर तय किए गए इन तीन तरीकों का इस्तेमाल करके, परफ़ॉर्मेंस एंट्री ऐक्सेस कर सकते थे:
इन एपीआई का इस्तेमाल अब भी किया जा सकता है. हालांकि, हमारा सुझाव है कि इनका इस्तेमाल न करें. इसकी वजह यह है कि इनसे यह पता नहीं चलता कि नई एंट्री कब जोड़ी गई हैं. इसके अलावा, कई नए एपीआई (जैसे कि largest-contentful-paint) को performance ऑब्जेक्ट के ज़रिए नहीं दिखाया जाता है. इन्हें सिर्फ़ PerformanceObserver के ज़रिए दिखाया जाता है.
अगर आपको Internet Explorer के साथ काम करने वाले कोड की ज़रूरत नहीं है, तो बेहतर होगा कि आप अपने कोड में इन तरीकों का इस्तेमाल न करें और आगे से PerformanceObserver का इस्तेमाल करें.
User Timing API
User Timing API, समय के आधार पर तय की जाने वाली मेट्रिक के लिए, सामान्य तौर पर इस्तेमाल किया जाने वाला मेज़रमेंट एपीआई है. इसकी मदद से, किसी भी समय पॉइंट मार्क किए जा सकते हैं. इसके बाद, उन मार्क के बीच की अवधि को मेज़र किया जा सकता है.
// Record the time immediately before running a task.
performance.mark('myTask:start');
await doMyTask();
// Record the time immediately after running a task.
performance.mark('myTask:end');
// Measure the delta between the start and end of the task
performance.measure('myTask', 'myTask:start', 'myTask:end');
Date.now() या performance.now() जैसे एपीआई से भी आपको मिलती-जुलती सुविधाएं मिलती हैं. हालांकि, User Timing API का इस्तेमाल करने का फ़ायदा यह है कि यह परफ़ॉर्मेंस टूलिंग के साथ अच्छी तरह से इंटिग्रेट हो जाता है. उदाहरण के लिए, Chrome DevTools, परफ़ॉर्मेंस पैनल में उपयोगकर्ता के समय की मेज़रमेंट को दिखाता है. साथ ही, कई Analytics सेवा देने वाली कंपनियां, आपके किए गए किसी भी मेज़रमेंट को अपने-आप ट्रैक करती हैं. साथ ही, अवधि का डेटा अपने Analytics बैकएंड को भेजती हैं.
उपयोगकर्ता के समय की मेज़रमेंट की रिपोर्ट करने के लिए, PerformanceObserver का इस्तेमाल किया जा सकता है. साथ ही, measure टाइप की एंट्री देखने के लिए रजिस्टर किया जा सकता है:
// Create the performance observer.
const po = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// Log the entry and all associated details.
console.log(entry.toJSON());
}
});
// Start listening for `measure` entries to be dispatched.
po.observe({type: 'measure', buffered: true});
Long Tasks API
Long Tasks API से यह पता चलता है कि ब्राउज़र का मुख्य थ्रेड कब तक ब्लॉक रहता है. इससे फ़्रेम रेट या इनपुट लेटेन्सी पर असर पड़ता है. एपीआई, उन सभी टास्क की रिपोर्ट करेगा जिन्हें पूरा होने में 50 मिलीसेकंड से ज़्यादा समय लगता है.
जब भी आपको महंगा कोड चलाना हो या बड़ी स्क्रिप्ट लोड और एक्ज़ीक्यूट करनी हो, तो यह ट्रैक करना ज़रूरी होता है कि वह कोड मुख्य थ्रेड को ब्लॉक करता है या नहीं. दरअसल, कई हायर-लेवल मेट्रिक, Long Tasks API पर ही आधारित होती हैं. जैसे, इंटरैक्टिव होने में लगने वाला समय (टीटीआई) और कुल ब्लॉकिंग टाइम (टीबीटी).
लंबे समय तक चलने वाले टास्क कब होते हैं, यह पता लगाने के लिए PerformanceObserver का इस्तेमाल किया जा सकता है. साथ ही, longtask टाइप की एंट्री देखने के लिए रजिस्टर किया जा सकता है:
// Create the performance observer.
const po = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// Log the entry and all associated details.
console.log(entry.toJSON());
}
});
// Start listening for `longtask` entries to be dispatched.
po.observe({type: 'longtask', buffered: true});
Long Animation Frames API
Long Animation Frames API, Long Tasks API का नया वर्शन है. यह 50 मिलीसेकंड से ज़्यादा के लंबे फ़्रेम पर नज़र रखता है. यह लंबे टास्क पर नज़र नहीं रखता. इससे Long Tasks API की कुछ कमियां दूर होती हैं. जैसे, बेहतर एट्रिब्यूशन और संभावित रूप से समस्या पैदा करने वाली देरी का दायरा बढ़ना.
लंबे फ़्रेम कब होते हैं, यह पता लगाने के लिए PerformanceObserver का इस्तेमाल किया जा सकता है. साथ ही, long-animation-frame टाइप की एंट्री देखने के लिए रजिस्टर किया जा सकता है:
// Create the performance observer.
const po = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// Log the entry and all associated details.
console.log(entry.toJSON());
}
});
// Start listening for `long-animation-frame` entries to be dispatched.
po.observe({type: 'long-animation-frame', buffered: true});
Element Timing API
सबसे बड़ा कॉन्टेंटफ़ुल पेंट (एलसीपी) मेट्रिक से यह पता चलता है कि सबसे बड़ी इमेज या टेक्स्ट ब्लॉक को स्क्रीन पर कब रेंडर किया गया था. हालांकि, कुछ मामलों में आपको किसी दूसरे एलिमेंट को रेंडर होने में लगने वाले समय को मेज़र करना होता है.
ऐसे मामलों के लिए, Element Timing API का इस्तेमाल करें. LCP API, असल में एलिमेंट टाइमिंग API पर आधारित है. यह सबसे बड़े कॉन्टेंटफ़ुल एलिमेंट की परफ़ॉर्मेंस की रिपोर्ट अपने-आप जनरेट करता है. हालांकि, अन्य एलिमेंट की परफ़ॉर्मेंस की रिपोर्ट भी जनरेट की जा सकती है. इसके लिए, आपको उन एलिमेंट में elementtiming एट्रिब्यूट जोड़ना होगा. साथ ही, elementtiming एंट्री टाइप को मॉनिटर करने के लिए, PerformanceObserver को रजिस्टर करना होगा.element
<img elementtiming="hero-image" />
<p elementtiming="important-paragraph">This is text I care about.</p>
<!-- ... -->
<script>
const po = new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
// Log the entry and all associated details.
console.log(entry.toJSON());
}
});
// Start listening for `element` entries to be dispatched.
po.observe({type: 'element', buffered: true});
</script>
Event Timing API
पेज के रिस्पॉन्स में लगने वाला समय (आईएनपी) मेट्रिक से, पेज के रिस्पॉन्स में लगने वाले कुल समय का आकलन किया जाता है. इसके लिए, पेज पर किए गए सभी क्लिक, टैप, और कीबोर्ड इंटरैक्शन को देखा जाता है. किसी पेज का आईएनपी, आम तौर पर वह इंटरैक्शन होता है जिसे पूरा होने में सबसे ज़्यादा समय लगता है. यह समय, उपयोगकर्ता के इंटरैक्शन शुरू करने से लेकर ब्राउज़र के अगले फ़्रेम को पेंट करने तक का होता है. इस फ़्रेम में, उपयोगकर्ता के इनपुट का विज़ुअल नतीजा दिखता है.
आईएनपी मेट्रिक, Event Timing API की मदद से मेज़र की जाती है. यह एपीआई, इवेंट के लाइफ़साइकल के दौरान होने वाले कई टाइमस्टैंप दिखाता है. इनमें ये शामिल हैं:
startTime: वह समय जब ब्राउज़र को इवेंट मिलता है.processingStart: यह वह समय होता है, जब ब्राउज़र इवेंट के लिए इवेंट हैंडलर को प्रोसेस करना शुरू कर पाता है.processingEnd: यह वह समय होता है, जब ब्राउज़र इस इवेंट के लिए इवेंट हैंडलर से शुरू किए गए सभी सिंक्रोनस कोड को पूरा करता है.duration: यह वह समय होता है जब ब्राउज़र को इवेंट मिलता है और जब वह इवेंट हैंडलर से शुरू किए गए सभी सिंक्रोनस कोड को पूरा करने के बाद, अगले फ़्रेम को पेंट कर पाता है. सुरक्षा की वजहों से, इस समय को 8 मिलीसेकंड तक राउंड किया जाता है.
यहां दिए गए उदाहरण में, इन वैल्यू का इस्तेमाल करके कस्टम मेज़रमेंट बनाने का तरीका बताया गया है:
const po = new PerformanceObserver((entryList) => {
// Get the last interaction observed:
const entries = Array.from(entryList.getEntries()).forEach((entry) => {
// Get various bits of interaction data:
const inputDelay = entry.processingStart - entry.startTime;
const processingTime = entry.processingEnd - entry.processingStart;
const presentationDelay = entry.startTime + entry.duration - entry.processingEnd;
const duration = entry.duration;
const eventType = entry.name;
const target = entry.target || "(not set)"
console.log("----- INTERACTION -----");
console.log(`Input delay (ms): ${inputDelay}`);
console.log(`Event handler processing time (ms): ${processingTime}`);
console.log(`Presentation delay (ms): ${presentationDelay}`);
console.log(`Total event duration (ms): ${duration}`);
console.log(`Event type: ${eventType}`);
console.log(target);
});
});
// A durationThreshold of 16ms is necessary to include more
// interactions, since the default is 104ms. The minimum
// durationThreshold is 16ms.
po.observe({type: 'event', buffered: true, durationThreshold: 16});
Resource Timing API
Resource Timing API की मदद से डेवलपर को इस बारे में ज़्यादा जानकारी मिलती है कि किसी पेज के लिए संसाधन कैसे लोड किए गए थे. एपीआई के नाम के बावजूद, यह सिर्फ़ टाइमिंग का डेटा नहीं देता है. हालांकि, इसमें टाइमिंग का काफ़ी डेटा होता है. आपके पास इस तरह के अन्य डेटा का ऐक्सेस भी हो सकता है:
initiatorType: संसाधन को कैसे फ़ेच किया गया: जैसे कि<script>या<link>टैग से याfetch()कॉल से.nextHopProtocol: रिसॉर्स को फ़ेच करने के लिए इस्तेमाल किया गया प्रोटोकॉल, जैसे किh2याquic.encodedBodySize/decodedBodySize]: संसाधन का साइज़, एन्कोड किए गए या डिकोड किए गए फ़ॉर्मैट में (क्रमशः)transferSize: नेटवर्क पर ट्रांसफ़र किए गए रिसोर्स का साइज़. जब कैश मेमोरी से संसाधन पूरे किए जाते हैं, तो यह वैल्यूencodedBodySizeसे बहुत कम हो सकती है. कुछ मामलों में, यह शून्य भी हो सकती है. ऐसा तब होता है, जब कैश मेमोरी को फिर से पुष्टि करने की ज़रूरत नहीं होती.
transferSize प्रॉपर्टी का इस्तेमाल करके, कैश हिट रेट मेट्रिक या कैश की गई कुल संसाधन फ़ाइल का साइज़ मेट्रिक को मेज़र किया जा सकता है. इससे यह समझने में मदद मिलती है कि संसाधन को कैश करने की आपकी रणनीति, बार-बार आने वाले लोगों के लिए परफ़ॉर्मेंस पर किस तरह असर डालती है.
यहां दिए गए उदाहरण में, पेज के लिए अनुरोध किए गए सभी रिसॉर्स को लॉग किया गया है. साथ ही, यह भी बताया गया है कि कैश मेमोरी से हर रिसॉर्स को पूरा किया गया है या नहीं.
// Create the performance observer.
const po = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// If transferSize is 0, the resource was fulfilled using the cache.
console.log(entry.name, entry.transferSize === 0);
}
});
// Start listening for `resource` entries to be dispatched.
po.observe({type: 'resource', buffered: true});
Navigation Timing API
Navigation Timing API, Resource Timing API के जैसा ही होता है. हालांकि, यह सिर्फ़ नेविगेशन अनुरोधों की जानकारी देता है. navigation एंट्री टाइप, resource एंट्री टाइप जैसा ही होता है. हालांकि, इसमें सिर्फ़ नेविगेशन के अनुरोधों से जुड़ी कुछ अतिरिक्त जानकारी शामिल होती है. जैसे, DOMContentLoaded और load इवेंट कब ट्रिगर होते हैं.
सर्वर के जवाब देने में लगने वाले समय (टाइम टू फ़र्स्ट बाइट (टीटीएफ़बी)) को समझने के लिए, कई डेवलपर एक मेट्रिक को ट्रैक करते हैं. यह मेट्रिक, Navigation Timing API का इस्तेमाल करके उपलब्ध होती है. खास तौर पर, यह एंट्री का responseStart टाइमस्टैंप होता है.
// Create the performance observer.
const po = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// If transferSize is 0, the resource was fulfilled using the cache.
console.log('Time to first byte', entry.responseStart);
}
});
// Start listening for `navigation` entries to be dispatched.
po.observe({type: 'navigation', buffered: true});
सर्विस वर्कर का इस्तेमाल करने वाले डेवलपर के लिए, एक और मेट्रिक अहम हो सकती है. यह मेट्रिक, नेविगेशन के अनुरोधों के लिए सर्विस वर्कर के चालू होने का समय है. यह वह समय है जब ब्राउज़र, फ़ेच इवेंट को इंटरसेप्ट करना शुरू करने से पहले, सर्विस वर्कर थ्रेड को शुरू करता है.
किसी नेविगेशन अनुरोध के लिए, सर्विस वर्कर के शुरू होने का समय entry.responseStart और entry.workerStart के बीच के अंतर से तय किया जा सकता है.
// Create the performance observer.
const po = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log('Service Worker startup time:',
entry.responseStart - entry.workerStart);
}
});
// Start listening for `navigation` entries to be dispatched.
po.observe({type: 'navigation', buffered: true});
Server Timing API
Server Timing API की मदद से, अनुरोध से जुड़ा टाइमिंग डेटा को सर्वर से ब्राउज़र पर भेजा जा सकता है. इसके लिए, रिस्पॉन्स हेडर का इस्तेमाल किया जाता है. उदाहरण के लिए, किसी अनुरोध के लिए डेटाबेस में डेटा ढूंढने में कितना समय लगा, यह बताया जा सकता है. इससे सर्वर के धीमे होने की वजह से होने वाली परफ़ॉर्मेंस की समस्याओं को डीबग करने में मदद मिल सकती है.
तीसरे पक्ष की ऐनलिटिक्स सेवाएं इस्तेमाल करने वाले डेवलपर के लिए, Server Timing API ही एक ऐसा तरीका है जिससे सर्वर की परफ़ॉर्मेंस के डेटा को अन्य कारोबारी मेट्रिक से जोड़ा जा सकता है. ये मेट्रिक, ऐनलिटिक्स टूल मेज़र कर सकते हैं.
अपने जवाबों में सर्वर के समय का डेटा तय करने के लिए, Server-Timing रिस्पॉन्स हेडर का इस्तेमाल किया जा सकता है. यहां एक उदाहरण दिया गया है.
HTTP/1.1 200 OK
Server-Timing: miss, db;dur=53, app;dur=47.2
इसके बाद, अपने पेजों से इस डेटा को Resource Timing और Navigation Timing API की resource या navigation एंट्री, दोनों पर पढ़ा जा सकता है.
// Create the performance observer.
const po = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// Logs all server timing data for this response
console.log('Server Timing', entry.serverTiming);
}
});
// Start listening for `navigation` entries to be dispatched.
po.observe({type: 'navigation', buffered: true});