लेयर मॉडल
परिचय
ज़्यादातर वेब डेवलपर के लिए, डीओएम किसी वेब पेज का बुनियादी मॉडल होता है. रेंडरिंग, पेज के इस इलस्ट्रेशन को स्क्रीन पर एक इमेज में बदलने की प्रोसेस है. हाल के सालों में, आधुनिक ब्राउज़र ने ग्राफ़िक्स कार्ड का फ़ायदा पाने के लिए, रेंडरिंग के तरीके में बदलाव किया है: इसे अक्सर “हार्डवेयर एक्सेलरेशन” कहा जाता है. किसी सामान्य वेब पेज (जैसे, Canvas2D या WebGL नहीं) के बारे में बात करते समय, इस शब्द का क्या मतलब है? इस लेख में, उस बुनियादी मॉडल के बारे में बताया गया है जो Chrome में वेब कॉन्टेंट को हार्डवेयर से तेज़ी से रेंडर करने की सुविधा देता है.
ज़रूरी शर्तें
हम यहां WebKit के बारे में बात कर रहे हैं. खास तौर पर, हम WebKit के Chromium पोर्ट के बारे में बात कर रहे हैं. इस लेख में, Chrome को लागू करने के बारे में जानकारी दी गई है, न कि वेब प्लैटफ़ॉर्म की सुविधाओं के बारे में. वेब प्लैटफ़ॉर्म और स्टैंडर्ड, लागू करने के इस लेवल की जानकारी को कोड में नहीं डालते. इसलिए, इस लेख में बताई गई कोई भी बात दूसरे ब्राउज़र पर लागू होगी, इसकी कोई गारंटी नहीं है. हालांकि, बेहतर तरीके से डीबग करने और परफ़ॉर्मेंस को बेहतर बनाने के लिए, इंटरनल के बारे में जानकारी काम की हो सकती है.
यह भी ध्यान रखें कि इस पूरे लेख में, Chrome के रेंडरिंग आर्किटेक्चर के मुख्य हिस्से के बारे में बताया गया है. इसमें लगातार बदलाव हो रहे हैं. इस लेख में सिर्फ़ उन चीज़ों के बारे में बताया गया है जिनमें बदलाव होने की संभावना कम है. हालांकि, इस बात की कोई गारंटी नहीं है कि छह महीने बाद भी ये चीज़ें लागू रहेंगी.
यह समझना ज़रूरी है कि Chrome में, रेंडरिंग के लिए कुछ समय से दो अलग-अलग पाथ इस्तेमाल किए जा रहे हैं: हार्डवेयर से तेज़ी देने वाला पाथ और पुराना सॉफ़्टवेयर पाथ. फ़िलहाल, Windows, ChromeOS, और Android के लिए Chrome पर सभी पेज, हार्डवेयर की मदद से तेज़ी से लोड होते हैं. Mac और Linux पर, सिर्फ़ उन पेजों को तेज़ी से लोड किया जाता है जिनके कुछ कॉन्टेंट को कॉम्पोज़ करने की ज़रूरत होती है. कॉम्पोज़ करने की ज़रूरत के बारे में ज़्यादा जानने के लिए यहां देखें. हालांकि, जल्द ही सभी पेजों को तेज़ी से लोड किया जाएगा.
आखिर में, हम रेंडरिंग इंजन की सुविधाओं को बेहतर बनाने की कोशिश कर रहे हैं. इन सुविधाओं का परफ़ॉर्मेंस पर काफ़ी असर पड़ता है. अपनी साइट की परफ़ॉर्मेंस को बेहतर बनाने के लिए, लेयर मॉडल को समझना मददगार हो सकता है. हालांकि, इससे आपको नुकसान भी पहुंच सकता है: लेयर, काम के कॉन्स्ट्रक्ट होते हैं, लेकिन बहुत सारी लेयर बनाने से पूरे ग्राफ़िक स्टैक में ओवरहेड आ सकता है. आपको पहले ही चेतावनी दे दी गई है!
डीओएम से स्क्रीन पर
पेश है लेयर
जब कोई पेज लोड और पार्स हो जाता है, तो उसे ब्राउज़र में एक ऐसे स्ट्रक्चर के तौर पर दिखाया जाता है जिससे कई वेब डेवलपर वाकिफ होते हैं: DOM. हालांकि, किसी पेज को रेंडर करते समय, ब्राउज़र में इंटरमीडिएट रेप्रज़ेंटेशन की एक सीरीज़ होती है, जो सीधे तौर पर डेवलपर को नहीं दिखती. इनमें से सबसे अहम स्ट्रक्चर लेयर है.
Chrome में कई तरह की लेयर होती हैं: रेंडर लेयर, जो DOM के सबट्री के लिए ज़िम्मेदार होती हैं और ग्राफ़िक्स लेयर, जो रेंडर लेयर के सबट्री के लिए ज़िम्मेदार होती हैं. हमारे लिए, बाद वाला विकल्प सबसे दिलचस्प है, क्योंकि GraphicsLayers को टेक्स्चर के तौर पर जीपीयू में अपलोड किया जाता है. अब से, GraphicsLayer के लिए सिर्फ़ “लेयर” शब्द का इस्तेमाल किया जाएगा.
जीपीयू की शब्दावली के बारे में थोड़ी जानकारी: टेक्स्चर क्या है? इसे एक बिटमैप इमेज के तौर पर देखें, जिसे मुख्य मेमोरी (यानी, रैम) से वीडियो मेमोरी (यानी, आपके जीपीयू पर VRAM) में ले जाया गया है. जीपीयू पर डेटा भेजने के बाद, उसे मेश ज्यामिति पर मैप किया जा सकता है. वीडियो गेम या सीएडी प्रोग्राम में, इस तकनीक का इस्तेमाल स्केलेटल 3D मॉडल को “स्किन” देने के लिए किया जाता है. Chrome, वेब पेज के कॉन्टेंट के हिस्सों को जीपीयू पर भेजने के लिए टेक्सचर का इस्तेमाल करता है. टेक्सचर को आसानी से अलग-अलग पोज़िशन और ट्रांसफ़ॉर्मेशन पर मैप किया जा सकता है. इसके लिए, उन्हें एक बहुत ही आसान रेक्टैंगल मेश पर लागू करें. 3D सीएसएस इसी तरह काम करती है. यह तेज़ी से स्क्रोल करने के लिए भी बेहतरीन है. हालांकि, इन दोनों के बारे में हम बाद में ज़्यादा जानकारी देंगे.
लेयर के कॉन्सेप्ट को समझने के लिए, कुछ उदाहरण देखते हैं.
Chrome में लेयर का अध्ययन करते समय, “रेंडरिंग” हेडिंग में मौजूद डेवलपर टूल की सेटिंग (यानी छोटा कॉग आइकॉन) में “कंपोज़िटेड लेयर बॉर्डर दिखाएं” फ़्लैग एक बहुत ही काम का टूल है. यह आसानी से हाइलाइट करता है कि स्क्रीन पर लेयर कहां हैं. चलिए, इसे चालू करते हैं. ये सभी स्क्रीनशॉट और उदाहरण, Chrome Canary के सबसे नए वर्शन, Chrome 27 से लिए गए हैं.
इमेज 1: एक लेयर वाला पेज
<!doctype html>
<html>
<body>
<div>I am a strange root.</div>
</body>
</html>
![पेज की बेस लेयर के चारों ओर, कॉम्पोज़िट लेयर रेंडर बॉर्डर का स्क्रीनशॉट](https://web.developers.google.cn/static/articles/speed-layers/image/screenshot-composited-la-06c0fd7a766ad.png?hl=hi)
इस पेज में सिर्फ़ एक लेयर है. नीले ग्रिड में टाइल दिखती हैं. इन्हें किसी लेयर की सब-इकाइयों के तौर पर देखा जा सकता है. Chrome, बड़ी लेयर के हिस्सों को एक बार में जीपीयू पर अपलोड करने के लिए इनका इस्तेमाल करता है. यहां ये ज़्यादा ज़रूरी नहीं हैं.
इमेज 2: अपनी लेयर में मौजूद एलिमेंट
<!doctype html>
<html>
<body>
<div style="transform: rotateY(30deg) rotateX(-30deg); width: 200px;">
I am a strange root.
</div>
</body>
</html>
![घुमाई गई लेयर के रेंडर बॉर्डर का स्क्रीनशॉट](https://web.developers.google.cn/static/articles/speed-layers/image/screenshot-rotated-layer-dedef7c7c3743.png?hl=hi)
<div>
पर 3D सीएसएस प्रॉपर्टी डालकर, उसे घुमाया जा सकता है. इससे यह देखा जा सकता है कि जब किसी एलिमेंट को अपनी लेयर मिलती है, तो वह कैसा दिखता है: इस व्यू में, ऑरेंज बॉर्डर पर ध्यान दें. यह बॉर्डर, लेयर की आउटलाइन दिखाता है.
लेयर बनाने की शर्तें
और किन चीज़ों को अपनी लेयर मिलती है? Chrome के हेयुरिस्टिक्स (अनुमान लगाने के लिए इस्तेमाल होने वाले तरीके) समय के साथ बेहतर होते रहे हैं और अब भी बेहतर होते जा रहे हैं. हालांकि, फ़िलहाल लेयर बनाने के लिए, इनमें से कोई भी ट्रिगर काम करता है:
- 3D या पर्सपेक्टिव ट्रांसफ़ॉर्म की सीएसएस प्रॉपर्टी
<video>
एलिमेंट, जिनमें तेज़ी से वीडियो डिकोड करने की सुविधा का इस्तेमाल किया गया है<canvas>
3D (WebGL) कॉन्टेक्स्ट या बेहतर 2D कॉन्टेक्स्ट वाले एलिमेंट- कम्पोज़िट किए गए प्लग इन (जैसे, Flash)
- ऐसे एलिमेंट जिनकी ऑपैसिटी के लिए सीएसएस ऐनिमेशन का इस्तेमाल किया गया हो या ऐनिमेट किए गए ट्रांसफ़ॉर्म का इस्तेमाल किया गया हो
- तेज़ी से काम करने वाले सीएसएस फ़िल्टर वाले एलिमेंट
- एलिमेंट का कोई वंशज है, जिसमें कॉम्पोज़िटिंग लेयर है. दूसरे शब्दों में, अगर एलिमेंट का कोई चाइल्ड एलिमेंट है, जो अपनी लेयर में है
- एलिमेंट का कोई ऐसा सिबलिंग है जिसका z-index कम है और जिसमें कंपोज़िटिंग लेयर है. दूसरे शब्दों में, इसे कंपोज़िट की गई लेयर के ऊपर रेंडर किया जाता है
व्यावहारिक नतीजे: ऐनिमेशन
लेयर को एक जगह से दूसरी जगह भी ले जाया जा सकता है. इससे, उन्हें एनिमेशन के लिए बहुत ज़्यादा काम का बना दिया जाता है.
इमेज 3: ऐनिमेशन वाली लेयर
<!doctype html>
<html>
<head>
<style>
div {
animation-duration: 5s;
animation-name: slide;
animation-iteration-count: infinite;
animation-direction: alternate;
width: 200px;
height: 200px;
margin: 100px;
background-color: gray;
}
@keyframes slide {
from {
transform: rotate(0deg);
}
to {
transform: rotate(120deg);
}
}
</style>
</head>
<body>
<div>I am a strange root.</div>
</body>
</html>
जैसा कि हमने पहले बताया था, लेयर, स्टैटिक वेब कॉन्टेंट को एक से दूसरी जगह ले जाने के लिए काफ़ी काम की होती हैं. आम तौर पर, Chrome किसी लेयर के कॉन्टेंट को सॉफ़्टवेयर बिटमैप में पेंट करता है. इसके बाद, उसे टेक्स्चर के तौर पर जीपीयू पर अपलोड करता है. अगर आने वाले समय में उस कॉन्टेंट में कोई बदलाव नहीं होता है, तो उसे फिर से पेंट करने की ज़रूरत नहीं है. यह एक अच्छी बात है: फिर से पेंट करने में समय लगता है. इस समय का इस्तेमाल, JavaScript चलाने जैसे दूसरे कामों के लिए किया जा सकता है. अगर पेंट करने में ज़्यादा समय लगता है, तो ऐनिमेशन में रुकावट या देरी होती है.
उदाहरण के लिए, Dev Tools की टाइमलाइन का यह व्यू देखें: इस लेयर के आगे-पीछे घूमने के दौरान, पेन्ट करने की कोई कार्रवाई नहीं होती.
![ऐनिमेशन के दौरान, Dev Tools की टाइमलाइन का स्क्रीनशॉट](https://web.developers.google.cn/static/articles/speed-layers/image/screenshot-dev-tools-tim-450d45c637919.png?hl=hi)
अमान्य है! फिर से पेंट करना
हालांकि, अगर लेयर का कॉन्टेंट बदलता है, तो उसे फिर से पेंट करना होगा.
इमेज 4: लेयर को फिर से पेंट करना
<!doctype html>
<html>
<head>
<style>
div {
animation-duration: 5s;
animation-name: slide;
animation-iteration-count: infinite;
animation-direction: alternate;
width: 200px;
height: 200px;
margin: 100px;
background-color: gray;
}
@keyframes slide {
from {
transform: rotate(0deg);
}
to {
transform: rotate(120deg);
}
}
</style>
</head>
<body>
<div id="foo">I am a strange root.</div>
<input id="paint" type="button" value="repaint">
<script>
var w = 200;
document.getElementById('paint').onclick = function() {
document.getElementById('foo').style.width = (w++) + 'px';
}
</script>
</body>
</html>
इनपुट एलिमेंट पर हर बार क्लिक करने पर, घूमने वाला एलिमेंट 1 पिक्सल चौड़ा हो जाता है. इससे पूरे एलिमेंट का रीलेआउट और फिर से रंग भरना पड़ता है. इस मामले में, यह पूरी लेयर होती है.
Dev Tools में “पेंट किए गए हिस्से दिखाएं” टूल की मदद से, यह देखा जा सकता है कि क्या पेंट किया जा रहा है. यह टूल, Dev Tools की सेटिंग में “रेंडरिंग” सेक्शन में भी मौजूद होता है. इसे चालू करने के बाद, ध्यान दें कि बटन पर क्लिक करने पर, ऐनिमेशन वाला एलिमेंट और बटन, दोनों लाल रंग में फ़्लैश करते हैं.
![पेंट किए गए आयत दिखाने वाले चेकबॉक्स का स्क्रीनशॉट](https://web.developers.google.cn/static/articles/speed-layers/image/screenshot-show-paint-re-28fb10bb918a6.png?hl=hi)
पेंट इवेंट, Dev Tools की टाइमलाइन में भी दिखते हैं. ध्यान से पढ़ने वाले लोगों को पता चल सकता है कि यहां दो पेंट इवेंट हैं: एक लेयर के लिए और दूसरा बटन के लिए. बटन को दबाने पर/उसकी स्थिति बदलने पर, उसे फिर से पेंट किया जाता है.
![Dev Tools टाइमलाइन का स्क्रीनशॉट, जिसमें किसी लेयर को फिर से रंगा जा रहा है](https://web.developers.google.cn/static/articles/speed-layers/image/screenshot-dev-tools-tim-ac9ba1b298e75.png?hl=hi)
ध्यान दें कि Chrome को हमेशा पूरी लेयर को फिर से पेंट करने की ज़रूरत नहीं होती. यह डीओएम के सिर्फ़ उस हिस्से को फिर से पेंट करने की कोशिश करता है जो अमान्य हो गया है. इस मामले में, हमने जिस डीओएम एलिमेंट में बदलाव किया है वह पूरी लेयर का साइज़ है. हालांकि, कई अन्य मामलों में, एक लेयर में कई DOM एलिमेंट होंगे.
अगला सवाल यह है कि अमान्य होने की वजह क्या है और फिर से पेंट करने की ज़रूरत क्यों पड़ती है. इस सवाल का पूरा जवाब देना मुश्किल है, क्योंकि ऐसे कई मामले हैं जिनकी वजह से पुष्टि अमान्य हो सकती है. आम तौर पर, सीएसएस स्टाइल में बदलाव करके या फिर फिर से लेआउट करने की वजह से, डीओएम में गड़बड़ी होती है. टोनी जेंटिलकोर ने फिर से लेआउट बनाने की वजह के बारे में एक बेहतरीन ब्लॉग पोस्ट लिखी है. वहीं, स्टोयन स्टेफ़ानोव ने पेंटिंग के बारे में ज़्यादा जानकारी देने वाला लेख लिखा है. हालांकि, यह लेख सिर्फ़ पेंटिंग के बारे में है, इसमें कॉम्पोज़िटिंग के बारे में नहीं बताया गया है.
यह पता लगाने का सबसे अच्छा तरीका है कि क्या इसकी वजह से, उस चीज़ पर असर पड़ रहा है जिस पर आप काम कर रहे हैं. इसके लिए, Dev Tools टाइमलाइन और 'पेंट किए गए हिस्से दिखाएं' टूल का इस्तेमाल करें. इससे यह पता चलेगा कि क्या आपको पेज को फिर से पेंट करने की ज़रूरत है या नहीं. इसके बाद, यह पता लगाने की कोशिश करें कि रीलेआउट/फिर से पेंट करने से ठीक पहले, आपने DOM को कहां गंदा किया था. अगर पेटिंग करना ज़रूरी है, लेकिन इसमें बहुत ज़्यादा समय लग रहा है, तो Dev Tools में लगातार पेटिंग मोड के बारे में एबरहार्ड ग्रैथर का लेख पढ़ें.
इसे एक साथ रखना: डीओएम से स्क्रीन
तो Chrome, DOM को स्क्रीन इमेज में कैसे बदलता है? कॉन्सेप्ट के हिसाब से, यह:
- डीओएम को लेता है और उसे लेयर में बांटता है
- इनमें से हर लेयर को सॉफ़्टवेयर बिटमैप में अलग-अलग पेंट करता है
- उन्हें जीपीयू में टेक्सचर के तौर पर अपलोड करता है
- अलग-अलग लेयर को फ़ाइनल स्क्रीन इमेज में एक साथ जोड़ता है.
Chrome को पहली बार किसी वेब पेज का फ़्रेम जनरेट करते समय, यह सब करना होगा. हालांकि, आने वाले समय में फ़्रेम के लिए, कुछ शॉर्टकट इस्तेमाल किए जा सकते हैं:
- अगर सीएसएस की कुछ प्रॉपर्टी में बदलाव होता है, तो फिर से पेज को पेंट करने की ज़रूरत नहीं होती. Chrome, पहले से ही GPU पर मौजूद टेक्सचर के तौर पर मौजूद लेयर को फिर से कॉम्पोज़ कर सकता है.हालांकि, ऐसा अलग-अलग कॉम्पोज़िंग प्रॉपर्टी के साथ किया जा सकता है. जैसे, अलग-अलग पोज़िशन में, अलग-अलग ओपैसिटी वगैरह के साथ.
- अगर किसी लेयर का कोई हिस्सा अमान्य हो जाता है, तो उसे फिर से पेंट करके अपलोड किया जाता है. अगर इसका कॉन्टेंट एक जैसा रहता है, लेकिन इसके कॉम्पोज़ किए गए एट्रिब्यूट बदल जाते हैं (उदाहरण के लिए, इसका अनुवाद हो जाता है या उसकी ओपैसिटी बदल जाती है), तो Chrome इसे GPU पर छोड़ सकता है और नया फ़्रेम बनाने के लिए, इसे फिर से कॉम्पोज़ कर सकता है.
अब आपको यह साफ़ तौर पर पता चल गया होगा कि लेयर पर आधारित कॉम्पोज़िंग मॉडल का रेंडरिंग की परफ़ॉर्मेंस पर काफ़ी असर पड़ता है. जब कुछ भी पेंट करने की ज़रूरत नहीं होती, तो कॉम्पोज़िट करना तुलनात्मक रूप से सस्ता होता है. इसलिए, रेंडरिंग की परफ़ॉर्मेंस को डीबग करने के दौरान, लेयर को फिर से पेंट करने से बचना एक अच्छा लक्ष्य होता है. जानकार डेवलपर, ऊपर दी गई कॉम्पोज़िटिंग ट्रिगर की सूची देखेंगे और उन्हें पता चलेगा कि लेयर बनाने के लिए, फ़ोर्स करने की सुविधा का इस्तेमाल किया जा सकता है. हालांकि, इन्हें बिना सोचे-समझे न बनाएं, क्योंकि ये बिना किसी शुल्क के उपलब्ध नहीं होते: ये सिस्टम रैम और जीपीयू (खास तौर पर मोबाइल डिवाइसों पर) में मेमोरी लेते हैं. साथ ही, इनमें से कई होने पर, यह तय करने के लॉजिक में अन्य ओवरहेड शामिल हो सकते हैं कि कौनसे विज्ञापन दिखें. अगर लेयर बड़ी हैं और वे पहले जहां नहीं ओवरलैप करती थीं वहां ओवरलैप करती हैं, तो कई लेयर की वजह से रेस्टर करने में लगने वाला समय भी बढ़ सकता है. इस वजह से, कभी-कभी इसे “ओवरड्रॉ” कहा जाता है. इसलिए, अपनी जानकारी का सही इस्तेमाल करें!
अभी के लिए बस इतना ही. लेयर मॉडल के व्यावहारिक असर के बारे में कुछ और लेखों के लिए, हमारे साथ बने रहें.