JavaScript निष्पादन ऑप्टिमाइज़ करें

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

पॉल लुइस
पॉल लुइस

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

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

हालांकि, कुछ ऐसे काम हैं जो JavaScript को सही तरीके से चलाने में अपने ऐप्लिकेशन की मदद करने के लिए, बेशक किए जा सकते हैं.

खास जानकारी

  • विज़ुअल अपडेट के लिए, setTimeout या setइंटरनल का इस्तेमाल न करें. इसकी जगह हमेशा requestAnimationFrame का इस्तेमाल करें.
  • लंबे समय से चल रहे JavaScript को मुख्य थ्रेड से वेब वर्कर पर ले जाएं.
  • कई फ़्रेम में DOM बदलाव करने के लिए, माइक्रो-टास्क का इस्तेमाल करें.
  • JavaScript के असर का आकलन करने के लिए, Chrome DevTools की टाइमलाइन और JavaScript प्रोफ़ाइलर का इस्तेमाल करें.

विज़ुअल बदलाव करने के लिए, requestAnimationFrame का इस्तेमाल करें

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

/**
    * If run as a requestAnimationFrame callback, this
    * will be run at the start of the frame.
    */
function updateScreen(time) {
    // Make visual updates here.
}

requestAnimationFrame(updateScreen);

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

setTimeout की वजह से, ब्राउज़र में कोई फ़्रेम छूट जाता है.

असल में, jQuery setTimeout के animate के काम करने के लिए इस्तेमाल किया जाता है. इसे बदला गया है, ताकि वर्शन 3 में requestAnimationFrame का इस्तेमाल किया जा सके. अगर आप jQuery का पुराना वर्शन इस्तेमाल कर रहे हैं, तो आप इसे requestAnimationFrame का इस्तेमाल करने के लिए, पैच करने की सलाह देंगे.

जटिलता को कम करना या वेब वर्कर का इस्तेमाल करना

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

आपको इस बात की सूझ-बूझ के साथ चर्चा करनी चाहिए कि JavaScript कब और कितनी देर तक चलता है. उदाहरण के लिए, अगर आप स्क्रोल करने जैसे ऐनिमेशन में हैं, तो आपको अपने JavaScript को 3-4 मि॰से॰ के क्षेत्र में ही रखना चाहिए. इससे ज़्यादा समय लेने पर, इसमें बहुत ज़्यादा समय लगने का खतरा होता है. अगर आपको कुछ समय का इस्तेमाल नहीं करना है, तो आप इसमें लगने वाले समय को लेकर ज़्यादा आराम से रह सकते हैं.

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

var dataSortWorker = new Worker("sort-worker.js");
dataSortWorker.postMesssage(dataToSort);

// The main thread is now free to continue working on other things...

dataSortWorker.addEventListener('message', function(evt) {
    var sortedData = evt.data;
    // Update data on screen...
});

सभी काम इस मॉडल में फ़िट नहीं हो सकते: वेब वर्कर के पास DOM का ऐक्सेस नहीं है. जहां आपका काम मुख्य थ्रेड पर होना चाहिए, वहां बैच बनाने की प्रोसेस का इस्तेमाल करें. इसमें बड़े टास्क को छोटे-छोटे टास्क में बांटा जा सकता है. हर टास्क में कुछ मिलीसेकंड से ज़्यादा नहीं लगते. साथ ही, यह हर फ़्रेम में requestAnimationFrame हैंडलर में चलाया जा सकता है.

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

अपने JavaScript के “फ़्रेम टैक्स” के बारे में जानना

किसी फ़्रेमवर्क, लाइब्रेरी या अपने कोड का आकलन करते समय, यह आकलन करना ज़रूरी है कि फ़्रेम-दर-फ़्रेम के हिसाब से JavaScript कोड को चलाने में कितना खर्च आता है. खास तौर पर, यह तब ज़रूरी होता है, जब ऐनिमेशन बदलने या स्क्रोल करने जैसे परफ़ॉर्मेंस के लिए अहम काम किया जा रहा हो.

Chrome DevTools का परफ़ॉर्मेंस पैनल, JavaScript की लागत को मेज़र करने का सबसे अच्छा तरीका है. आम तौर पर, आपको इस तरह के लो-लेवल रिकॉर्ड मिलते हैं:

Chrome DevTools में परफ़ॉर्मेंस को रिकॉर्ड करना

मुख्य सेक्शन में JavaScript कॉल का फ़्लेम चार्ट मौजूद होता है. इससे कॉल के दौरान यह पता लगाने में मदद मिलती है कि किन फ़ंक्शन को कॉल किया गया था और उनमें से हर फ़ंक्शन को कॉल में कितना समय लगा था.

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

परफ़ॉर्मेंस पैनल को इस्तेमाल करने का तरीका जानने के लिए, रनटाइम की परफ़ॉर्मेंस का विश्लेषण करके शुरुआत करें देखें.

अपने JavaScript को माइक्रो-ऑप्टिमाइज़ करने से बचें

यह जानना अच्छा होगा कि ब्राउज़र किसी चीज़ के एक वर्शन को दूसरी चीज़ से 100 गुना ज़्यादा तेज़ी से एक्ज़ीक्यूट कर सकता है, जैसे किसी एलिमेंट के offsetTop का अनुरोध करना, गणना करने से ज़्यादा तेज़ है getBoundingClientRect(), लेकिन यह हमेशा सही होता है कि आप हर फ़्रेम में बहुत कम बार ही कॉल करने वाले फ़ंक्शन को कॉल करेंगे. इसलिए, JavaScript के परफ़ॉर्मेंस के इस पहलू पर ध्यान देने की कोशिश करना आम तौर पर बेकार होता है. आम तौर पर, कुछ मिलीसेकंड ही सेव किए जाते हैं.

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

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