उपयोगकर्ता समय API

अपने वेब ऐप्लिकेशन को समझना

Alex Danilo

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

जिस चीज़ को मेज़र नहीं किया जा सकता उसे ऑप्टिमाइज़ नहीं किया जा सकता

धीमी गति से काम करने वाले वेब ऐप्लिकेशन की स्पीड बढ़ाने के लिए, सबसे पहले यह पता लगाना ज़रूरी है कि किस वजह से ऐप्लिकेशन धीमा है. JavaScript कोड के अलग-अलग हिस्सों को लागू होने में लगने वाले समय का आकलन करना, हॉट स्पॉट की पहचान करने का सबसे सही तरीका है. इससे परफ़ॉर्मेंस को बेहतर बनाने के तरीके खोजने में मदद मिलती है. अच्छी बात यह है कि User Timing API की मदद से, JavaScript के अलग-अलग हिस्सों में एपीआई कॉल डाले जा सकते हैं. इसके बाद, समय से जुड़ा ज़्यादा जानकारी वाला डेटा निकाला जा सकता है. इस डेटा का इस्तेमाल करके, साइट को ऑप्टिमाइज़ किया जा सकता है.

हाई रिज़ॉल्यूशन समय और now()

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

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

var myTime = window.performance.now();

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

DOMHighResTimeStamp टाइप

पहले, वेब ऐप्लिकेशन का समय तय करने के लिए, Date.now() जैसी किसी चीज़ का इस्तेमाल किया जाता था. इससे DOMTimeStamp मिलता था. DOMTimeStamp, वैल्यू के तौर पर मिलीसेकंड की संख्या दिखाता है. हाई रिज़ॉल्यूशन टाइम के लिए ज़रूरी ज़्यादा सटीक जानकारी देने के लिए, DOMHighResTimeStamp नाम का एक नया टाइप पेश किया गया. यह टाइप, फ़्लोटिंग पॉइंट वैल्यू है. यह मिलीसेकंड में समय भी दिखाता है. हालांकि, फ़्लोटिंग पॉइंट होने की वजह से, वैल्यू मिलीसेकंड के फ़्रैक्शन को दिखा सकती है. इसलिए, इससे मिलीसेकंड के एक हज़ारवें हिस्से तक की सटीक जानकारी मिल सकती है.

उपयोगकर्ता समय का इंटरफ़ेस

अब हमारे पास हाई रिज़ॉल्यूशन वाले टाइम स्टैंप हैं. इसलिए, समय की जानकारी निकालने के लिए, उपयोगकर्ता समय इंटरफ़ेस का इस्तेमाल करें.

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

mark() का इस्तेमाल करना

mark() तरीका, टाइमिंग के विश्लेषण के लिए हमारे टूलकिट का मुख्य टूल है. mark() हमारे लिए टाइम स्टैंप सेव करता है. mark() की सबसे अच्छी बात यह है कि हम टाइमस्टैंप को नाम दे सकते हैं. साथ ही, एपीआई उस नाम और टाइमस्टैंप को एक यूनिट के तौर पर याद रखेगा.

अपने ऐप्लिकेशन में अलग-अलग जगहों पर mark() को कॉल करने से, आपको यह पता चलता है कि आपके वेब ऐप्लिकेशन में उस ‘मार्क’ तक पहुंचने में कितना समय लगा.

इस स्पेसिफ़िकेशन में, मार्क के लिए सुझाए गए कई नाम शामिल हैं. ये नाम दिलचस्प हो सकते हैं और इन्हें आसानी से समझा जा सकता है. जैसे, mark_fully_loaded, mark_fully_visible,mark_above_the_fold वगैरह.

उदाहरण के लिए, हम इस कोड का इस्तेमाल करके, ऐप्लिकेशन के पूरी तरह से लोड होने पर एक मार्क सेट कर सकते हैं:

window.performance.mark('mark_fully_loaded');

अपने वेब ऐप्लिकेशन में नाम वाले मार्क सेट करके, हम समय से जुड़ा बहुत सारा डेटा इकट्ठा कर सकते हैं. साथ ही, हम अपनी सुविधा के हिसाब से उसका विश्लेषण करके यह पता लगा सकते हैं कि ऐप्लिकेशन क्या और कब कर रहा है.

measure() की मदद से माप का हिसाब लगाना

टाइमिंग मार्क का एक सेट सेट करने के बाद, आपको उनके बीच बीता हुआ समय पता करना होगा. ऐसा करने के लिए, measure() तरीके का इस्तेमाल किया जाता है.

measure() तरीका, मार्क के बीच बीते समय का हिसाब लगाता है. साथ ही, यह आपके मार्क और PerformanceTiming इंटरफ़ेस में मौजूद, जाने-माने इवेंट के नामों के बीच के समय को भी मेज़र कर सकता है.

उदाहरण के लिए, डीओएम के पूरा होने से लेकर आपके ऐप्लिकेशन की स्थिति पूरी तरह से लोड होने तक के समय का पता लगाया जा सकता है. इसके लिए, इस तरह के कोड का इस्तेमाल करें:

window.performance.measure('measure_load_from_dom', 'domComplete', 'mark_fully_loaded');

measure() को कॉल करने पर, यह आपके सेट किए गए मार्क से अलग नतीजा सेव करता है, ताकि आप उन्हें बाद में वापस पा सकें. ऐप्लिकेशन के चलने के दौरान, समय को सेव करके ऐप्लिकेशन को रिस्पॉन्सिव बनाए रखा जा सकता है. साथ ही, ऐप्लिकेशन के कुछ काम पूरे होने के बाद, सारा डेटा डंप किया जा सकता है, ताकि बाद में उसका विश्लेषण किया जा सके.

clearMarks() के साथ मार्क खारिज करना

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

clearMarks() को कॉल करके, सेट किए गए किसी भी मार्क को आसानी से हटाया जा सकता है.

इसलिए, नीचे दिया गया उदाहरण कोड आपके सभी मौजूदा मार्क को हटा देगा, ताकि आप चाहें, तो फिर से टाइमिंग रन सेट अप कर सकें.

window.performance.clearMarks();

हालांकि, कुछ मामलों में ऐसा हो सकता है कि आपको सभी मार्क न मिटाने हों. इसलिए, अगर आपको कुछ खास मार्क हटाने हैं, तो आपको सिर्फ़ उस मार्क का नाम पास करना होगा जिसे हटाना है. उदाहरण के लिए, यहां दिया गया कोड:

window.performance.clearMarks('mark_fully_loaded');

यह पहले उदाहरण में सेट किए गए मार्क को हटा देता है. हालांकि, सेट किए गए अन्य मार्क में कोई बदलाव नहीं करता.

ऐसा हो सकता है कि आपको अपने बनाए गए किसी भी मेज़रमेंट को हटाना हो. इसके लिए, clearMeasures() नाम का एक तरीका है. यह ठीक उसी तरह काम करता है जिस तरह clearMarks() करता है. हालांकि, यह आपके किए गए किसी भी मेज़रमेंट पर काम करता है. उदाहरण के लिए, यह कोड:

window.performance.clearMeasures('measure_load_from_dom');

ऊपर दिए गए measure() उदाहरण में, हमने जो मेज़रमेंट किया था उसे हटा देगा. अगर आपको सभी मेज़र हटाने हैं, तो यह clearMarks() की तरह ही काम करता है. इसके लिए, आपको बिना आर्ग्युमेंट के clearMeasures() को कॉल करना होगा.

समय से जुड़ा डेटा पाना

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

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

यहां दिया गया कोड:

var items = window.performance.getEntriesByType('mark');

यह हमारे वेब ऐप्लिकेशन में हिट किए गए सभी मार्क की सूची दिखाता है. वहीं, यह कोड:

var items = window.performance.getEntriesByType('measure');

यह हमें उन सभी मेज़रमेंट की सूची दिखाता है जो हमने किए हैं.

आपने एंट्री को जो खास नाम दिया है उसका इस्तेमाल करके भी एंट्री की सूची वापस पाई जा सकती है. उदाहरण के लिए, यह कोड:

var items = window.performance.getEntriesByName('mark_fully_loaded');

इससे हमें एक आइटम वाली सूची मिलेगी. इसमें startTime प्रॉपर्टी में ‘mark_fully_loaded’ टाइमस्टैंप शामिल होगा.

XHR अनुरोध का समय तय करना (उदाहरण)

अब जब हमें User Timing API के बारे में काफ़ी जानकारी मिल गई है, तो हम इसका इस्तेमाल करके यह विश्लेषण कर सकते हैं कि हमारे वेब ऐप्लिकेशन में सभी XMLHttpRequests में कितना समय लगता है.

सबसे पहले, हम अपने सभी send() अनुरोधों में बदलाव करेंगे, ताकि मार्क सेट अप करने वाला फ़ंक्शन कॉल जारी किया जा सके. साथ ही, हम अपने सक्सेस कॉलबैक को ऐसे फ़ंक्शन कॉल से बदलेंगे जो दूसरा मार्क सेट करता है. इसके बाद, यह मेज़र करता है कि अनुरोध में कितना समय लगा.

आम तौर पर, हमारा XMLHttpRequest कुछ ऐसा दिखेगा:

var myReq = new XMLHttpRequest();
myReq.open('GET', url, true);
myReq.onload = function(e) {
  do_something(e.responseText);
}
myReq.send();

उदाहरण के लिए, हम अनुरोधों की संख्या को ट्रैक करने के लिए एक ग्लोबल काउंटर जोड़ेंगे. साथ ही, इसका इस्तेमाल हर अनुरोध के लिए एक मेज़रमेंट को स्टोर करने के लिए करेंगे. ऐसा करने के लिए कोड कुछ ऐसा दिखता है:

var reqCnt = 0;

var myReq = new XMLHttpRequest();
myReq.open('GET', url, true);
myReq.onload = function(e) {
  window.performance.mark('mark_end_xhr');
  reqCnt++;
  window.performance.measure('measure_xhr_' + reqCnt, 'mark_start_xhr', 'mark_end_xhr');
  do_something(e.responseText);
}
window.performance.mark('mark_start_xhr');
myReq.send();

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

जब वेब ऐप्लिकेशन कई अनुरोध कर लेता है, तो हम नीचे दिए गए कोड का इस्तेमाल करके, उन सभी को कंसोल में डंप कर सकते हैं:

var items = window.performance.getEntriesByType('measure');
for (var i = 0; i < items.length; ++i) {
  var req = items[i];
  console.log('XHR ' + req.name + ' took ' + req.duration + 'ms');
}

नतीजा

User Timing API आपको कई बेहतरीन टूल देता है. इन्हें अपने वेब ऐप्लिकेशन के किसी भी पहलू पर लागू किया जा सकता है. अपने वेब ऐप्लिकेशन में एपीआई कॉल को शामिल करके और जनरेट किए गए टाइमिंग डेटा को प्रोसेस करके, अपने ऐप्लिकेशन में हॉट-स्पॉट को आसानी से कम किया जा सकता है. इससे आपको यह साफ़ तौर पर पता चल पाएगा कि समय कहां खर्च हो रहा है. अगर आपका ब्राउज़र इस एपीआई के साथ काम नहीं करता, तो क्या होगा? कोई बात नहीं, आपको यहां एक बेहतरीन polyfill मिल सकता है, जो एपीआई को बहुत अच्छी तरह से एम्युलेट करता है. साथ ही, webpagetest.org के साथ भी अच्छी तरह से काम करता है. तो फिर इंतज़ार कैसा? अपने ऐप्लिकेशन पर User Timing API को अभी आज़माएं. इससे आपको ऐप्लिकेशन की स्पीड बढ़ाने में मदद मिलेगी. साथ ही, आपके उपयोगकर्ता आपको बेहतर अनुभव देने के लिए धन्यवाद देंगे.