ग़ैर-ज़रूरी पेंट से बचना

शुरुआती जानकारी

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

पेंटिंग: छोटा सा टूर

ब्राउज़र को अपने DOM और सीएसएस को स्क्रीन पर पिक्सल में बदलना है. यह काम एक मुश्किल प्रोसेस से किया जाता है. यह मार्कअप को पढ़ने से शुरू होता है और इससे एक डीओएम ट्री बन जाता है. यह सीएसएस के साथ इसी तरह काम करता है और उससे CSSOM बनाता है. इसके बाद, DOM और CSSOM को मिलाया जाता है और आखिरकार हम एक ऐसी संरचना पर पहुंच जाते हैं जहां से हम कुछ पिक्सल को पेंट करना शुरू कर सकते हैं.

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

Dom से पिक्सल

बात यह है कि एलिमेंट पर जो स्टाइल लागू की जाती हैं उनका असर, स्कीया के वर्कलोड पर पड़ता है. अगर एल्गोरिदम के हिसाब से भारी स्टाइल का इस्तेमाल किया जाता है, तो Skia को ज़्यादा काम करना होगा. Colt McAnlis ने सीएसएस किस तरह पेज रेंडर वेट पर असर पड़ता है, इसके बारे में एक लेख लिखा है. इस बारे में ज़्यादा जानकारी पाने के लिए, आपको इसे पढ़ना चाहिए.

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

स्क्रोल करना

ब्राउज़र में ऊपर या नीचे की ओर स्क्रोल करने पर, स्क्रीन पर कॉन्टेंट दिखने से पहले उसे फिर से पेंट करना होगा. अच्छी बात यह है कि बस एक छोटा सा हिस्सा ही रहेगा, लेकिन अगर ऐसा है, तो बनाए जाने वाले एलिमेंट में जटिल स्टाइल भी लागू की जा सकती हैं. इसलिए, अगर आपके पास पेंट करने के लिए छोटा सा इलाका है, तो इसका यह मतलब नहीं है कि यह काम जल्दी हो जाएगा.

यह देखने के लिए कि किन हिस्सों को फिर से पेंट किया जा रहा है, Chrome के DevTools में “ पेंट रेक्टैंगल दिखाएं” सुविधा का इस्तेमाल किया जा सकता है. इसके लिए, बस नीचे दाएं कोने में मौजूद छोटे से कॉग को दबाएं. इसके बाद, DevTools खोलें और अपने पेज के साथ इंटरैक्ट करें. इसके बाद, आपको फ़्लैश करने वाले रेक्टैंगल दिखेंगे. इनसे आपको पता चलेगा कि Chrome ने आपके पेज के किसी हिस्से को कहां और कब पेंट किया.

Chrome DevTools में पेंट रेक्टैंगल दिखाएं
Chrome DevTools में पेंट रेक्टैंगल दिखाएं

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

मैंने पहले स्क्रोल करने की परफ़ॉर्मेंस पर एक लेख लिखा था. अगर आपको स्क्रोलिंग परफ़ॉर्मेंस के बारे में और जानना है, तो उस पर एक नज़र डालें.

इंटरैक्शन

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

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

यह कॉम्बिनेशन अच्छा नहीं है

महंगे पेंट वाला डेमो
महंगे पेंट के साथ डेमो

अगर मैं माउस को एक साथ मूव कर दूं, तो क्या होगा? यह मुमकिन है कि मैं किसी एलिमेंट को स्क्रोल करते समय अनजाने में "इंटरैक्ट" कर ले. इससे महंगा पेंट ट्रिगर हो जाता है. इसका नतीजा यह हुआ कि मेरा फ़्रेम बजट ~16.7 मि॰से॰ (फ़्रेम प्रति सेकंड) तक पहुंचने के लिए ज़रूरी है. हमें इससे कम समय में 60 फ़्रेम प्रति सेकंड तक पहुंचना होगा. मैंने आपका डेमो बनाया है, ताकि मैं आपको सही जानकारी दिखा सकूँ. उम्मीद है कि जैसे-जैसे आप अपने माउस को स्क्रोल करेंगे और उसे हिलाएँगे, आपको होवर इफ़ेक्ट दिखेगा, लेकिन चलिए देखते हैं कि Chrome का DevTools इससे क्या बनता है:

Chrome का DevTools महंगे फ़्रेम दिखा रहा है
Chrome के DevTools में महंगे फ़्रेम दिखाए गए हैं

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

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

कोड यहां है:

// Used to track the enabling of hover effects
var enableTimer = 0;

/*
 * Listen for a scroll and use that to remove
 * the possibility of hover effects
 */
window.addEventListener('scroll', function() {
  clearTimeout(enableTimer);
  removeHoverClass();

  // enable after 1 second, choose your own value here!
  enableTimer = setTimeout(addHoverClass, 1000);
}, false);

/**
 * Removes the hover class from the body. Hover styles
 * are reliant on this class being present
 */
function removeHoverClass() {
  document.body.classList.remove('hover');
}

/**
 * Adds the hover class to the body. Hover styles
 * are reliant on this class being present
 */
function addHoverClass() {
  document.body.classList.add('hover');
}

जैसा कि आपको दिख रहा है कि हम यह ट्रैक करने के लिए मुख्य भाग पर क्लास का इस्तेमाल करते हैं कि कर्सर घुमाने पर दिखने वाले इफ़ेक्ट "अनुमति हैं" या नहीं. साथ ही, इस क्लास के मौजूद होने पर, उसके स्टाइल का इस्तेमाल किया जाता है:

/* Expect the hover class to be on the body
 before doing any hover effects */
.hover .block:hover {
 …
}

दर्शकों के लिए, प्रॉडक्ट खरीदने के बारे में बस इतना ही!

नतीजा

आपके ऐप्लिकेशन का आनंद लेने वाले लोगों के लिए, परफ़ॉर्मेंस को रेंडर करना ज़रूरी है. साथ ही, आपको हमेशा पेंट वर्कलोड 16 मि॰से॰ से कम पर रखना चाहिए. ऐसा करने के लिए, आपको अपनी पूरी डेवलपमेंट प्रोसेस के दौरान DevTools का इस्तेमाल करके इंटिग्रेट करना चाहिए. इससे, समस्याओं की पहचान करने और उन्हें ठीक करने में मदद मिलेगी.

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

अपनी साइटों और ऐप्लिकेशन पर एक नज़र डालें, क्या वे पेंट सुरक्षा की थोड़ी-बहुत सुरक्षा कर सकते हैं?