Chrome में तेज़ी से रेंडरिंग

लेयर मॉडल

Tom Wiltzius
Tom Wiltzius

परिचय

ज़्यादातर वेब डेवलपर के लिए, वेब पेज का बुनियादी मॉडल DOM होता है. रेंडरिंग, पेज के इस प्रज़ेंटेशन को स्क्रीन पर इमेज में बदलने की प्रोसेस है. यह प्रोसेस अक्सर साफ़ तौर पर नहीं दिखती. मॉडर्न ब्राउज़र ने हाल के सालों में रेंडरिंग के तरीके में बदलाव किया है, ताकि ग्राफ़िक कार्ड का फ़ायदा लिया जा सके: इसे अक्सर “हार्डवेयर से तेज़ी लाएं” कहा जाता है. सामान्य वेब पेज (जैसे, Canvas2D या WebGL नहीं) के बारे में बात करते समय, इस शब्द का असल मतलब क्या होता है? इस लेख में उस बुनियादी मॉडल के बारे में बताया गया है जो Chrome में वेब कॉन्टेंट की हार्डवेयर-ऐक्सेलरेटेड रेंडरिंग को बेहतर बनाता है.

बड़ी और अहम चेतावनियां

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

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

यह समझना ज़रूरी है कि Chrome में कुछ समय से रेंडरिंग के दो अलग-अलग पाथ मौजूद हैं: हार्डवेयर की मदद से तेज़ी लाने वाला पाथ और पुराना सॉफ़्टवेयर पाथ. यह लेख लिखे जाने तक, Windows, ChromeOS, और Android के लिए Chrome पर सभी पेज, हार्डवेयर से तेज़ी लाने की सुविधा का इस्तेमाल करते हैं. Mac और Linux पर, सिर्फ़ ऐसे पेज ऐक्सेलरेटेड पाथ पर जाते हैं जिनके कुछ कॉन्टेंट को कंपोज़िट करने की ज़रूरत होती है. कंपोज़िट करने की ज़रूरत कब होती है, इस बारे में ज़्यादा जानने के लिए यहां देखें. हालांकि, जल्द ही सभी पेज ऐक्सेलरेटेड पाथ पर जाएंगे.

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

डीओएम से स्क्रीन तक

पेश हैं लेयर

पेज लोड और पार्स होने के बाद, उसे ब्राउज़र में एक स्ट्रक्चर के तौर पर दिखाया जाता है. ज़्यादातर वेब डेवलपर इस स्ट्रक्चर को जानते हैं: डीओएम. हालांकि, किसी पेज को रेंडर करते समय, ब्राउज़र में इंटरमीडिएट रिप्रज़ेंटेशन की एक सीरीज़ होती है, जो डेवलपर को सीधे तौर पर नहीं दिखती. इनमें से सबसे अहम स्ट्रक्चर लेयर है.

Chrome में कई तरह की लेयर होती हैं: RenderLayers, जो डीओएम के सबट्री के लिए ज़िम्मेदार होती हैं और GraphicsLayers, जो RenderLayers के सबट्री के लिए ज़िम्मेदार होती हैं. हमारे लिए, GraphicsLayers सबसे दिलचस्प है, क्योंकि GraphicsLayers को जीपीयू पर टेक्सचर के तौर पर अपलोड किया जाता है. अब से मैं GraphicsLayer को सिर्फ़ “लेयर” कहूंगा.

जीपीयू की शब्दावली के बारे में खास जानकारी: टेक्सचर क्या होता है? इसे एक बिट मैप इमेज की तरह समझें, जिसे मुख्य मेमोरी (यानी रैम) से वीडियो मेमोरी (यानी आपके जीपीयू पर वीआरएएम) में ट्रांसफ़र किया गया है. जीपीयू पर आने के बाद, इसे मेश ज्यामिति पर मैप किया जा सकता है. वीडियो गेम या सीएडी प्रोग्राम में, इस तकनीक का इस्तेमाल स्केलेटल 3D मॉडल को “स्किन” देने के लिए किया जाता है. Chrome, वेब पेज के कॉन्टेंट के हिस्सों को जीपीयू पर लाने के लिए, टेक्सचर का इस्तेमाल करता है. टेक्सचर को बहुत ही आसान रेक्टैंगल मेश पर लागू करके, अलग-अलग पोज़िशन और ट्रांसफ़ॉर्मेशन पर सस्ते में मैप किया जा सकता है. 3D सीएसएस इसी तरह काम करती है. साथ ही, यह तेज़ी से स्क्रोल करने के लिए भी बेहतरीन है. हालांकि, इन दोनों के बारे में ज़्यादा जानकारी बाद में दी जाएगी.

लेयर के कॉन्सेप्ट को समझने के लिए, आइए कुछ उदाहरण देखते हैं.

Chrome में लेयर को समझने के लिए, Dev Tools में “रेंडरिंग” हेडिंग के तहत, सेटिंग (यानी कि छोटा कॉग आइकॉन) में मौजूद “कंपोज़िट लेयर के बॉर्डर दिखाएं” फ़्लैग एक बहुत ही काम का टूल है. यह बहुत आसानी से हाइलाइट करता है कि स्क्रीन पर लेयर कहां हैं. चलिए, इसे चालू करते हैं. ये स्क्रीनशॉट और उदाहरण, Chrome Canary के सबसे नए वर्शन से लिए गए हैं. यह लेख लिखे जाने के समय, Chrome 27 उपलब्ध था.

इमेज 1: एक लेयर वाला पेज

<!doctype html>
<html>
<body>
  <div>I am a strange root.</div>
</body>
</html>
पेज की बेस लेयर के आस-पास, कंपोज़िट लेयर रेंडर बॉर्डर का स्क्रीनशॉट
पेज की बेस लेयर के आस-पास, कंपोज़िट लेयर रेंडर बॉर्डर का स्क्रीनशॉट

इस पेज पर सिर्फ़ एक लेयर है. नीला ग्रिड, टाइल को दिखाता है. इन्हें किसी लेयर की सब-यूनिट के तौर पर देखा जा सकता है. Chrome इनका इस्तेमाल, किसी बड़ी लेयर के हिस्सों को एक बार में जीपीयू पर अपलोड करने के लिए करता है. यहां इनकी ज़रूरत नहीं है.

इमेज 2: अपनी लेयर में मौजूद एलिमेंट

<!doctype html>
<html>
<body>
  <div style="transform: rotateY(30deg) rotateX(-30deg); width: 200px;">
    I am a strange root.
  </div>
</body>
</html>
घुमाई गई लेयर के रेंडर बॉर्डर का स्क्रीनशॉट
घुमाई गई लेयर के रेंडर बॉर्डर का स्क्रीनशॉट

<div> पर 3D CSS प्रॉपर्टी लागू करके, उसे घुमाया जा सकता है. इससे हमें पता चलता है कि किसी एलिमेंट को अपनी लेयर मिलने पर वह कैसा दिखता है: नारंगी रंग के बॉर्डर पर ध्यान दें, जो इस व्यू में लेयर को आउटलाइन करता है.

लेयर बनाने की शर्तें

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

  • 3D या पर्सपेक्टिव ट्रांसफ़ॉर्म सीएसएस प्रॉपर्टी
  • <video> एलिमेंट, वीडियो को तेज़ी से डिकोड करने की सुविधा का इस्तेमाल कर रहे हैं
  • 3D (WebGL) कॉन्टेक्स्ट या ऐक्सेलरेटेड 2D कॉन्टेक्स्ट वाले <canvas> एलिमेंट
  • कंपोज़िट प्लगिन (जैसे, Flash)
  • ऐसे एलिमेंट जिनमें ओपैसिटी के लिए सीएसएस ऐनिमेशन का इस्तेमाल किया गया हो या ऐनिमेशन वाले ट्रांसफ़ॉर्म का इस्तेमाल किया गया हो
  • ऐक्सेलरेटेड सीएसएस फ़िल्टर वाले एलिमेंट
  • एलिमेंट में एक डिसेंडेंट है, जिसमें कंपोज़िटिंग लेयर है. दूसरे शब्दों में, अगर एलिमेंट में एक चाइल्ड एलिमेंट है, जो अपनी लेयर में है
  • एलिमेंट का एक सिबलिंग है, जिसका z-इंडेक्स कम है और जिसमें कंपोज़िटिंग लेयर है. दूसरे शब्दों में, इसे कंपोज़िट लेयर के ऊपर रेंडर किया जाता है

व्यावहारिक असर: ऐनिमेशन

हम लेयर को इधर-उधर भी ले जा सकते हैं. इससे ऐनिमेशन बनाने में काफ़ी मदद मिलती है.

इमेज 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 चलाने जैसे अन्य कामों के लिए किया जा सकता है. अगर पेंट में ज़्यादा समय लगता है, तो ऐनिमेशन में रुकावटें आती हैं या देरी होती है.

उदाहरण के लिए, DevTools की टाइमलाइन का यह व्यू देखें: जब यह लेयर आगे-पीछे घूमती है, तो कोई पेंट ऑपरेशन नहीं होता.

ऐनिमेशन के दौरान, Dev Tools की टाइमलाइन का स्क्रीनशॉट
ऐनिमेशन के दौरान DevTools की टाइमलाइन का स्क्रीनशॉट

अमान्य! फिर से पेंट करने की सेवा

हालांकि, अगर लेयर का कॉन्टेंट बदलता है, तो उसे फिर से पेंट करना पड़ता है.

इमेज 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>

इनपुट एलिमेंट पर हर बार क्लिक करने पर, घूमने वाला एलिमेंट एक पिक्सल चौड़ा हो जाता है. इसकी वजह से, पूरे एलिमेंट का लेआउट फिर से बनता है और उसे फिर से पेंट किया जाता है. इस मामले में, यह पूरी लेयर होती है.

क्या पेंट किया जा रहा है, यह देखने का एक अच्छा तरीका है, Dev Tools में “show paint rects” टूल का इस्तेमाल करना. यह टूल, Dev Tools की सेटिंग में “Rendering” हेडिंग के अंदर भी मौजूद होता है. इसे चालू करने के बाद, ध्यान दें कि बटन पर क्लिक करने पर, ऐनिमेशन वाला एलिमेंट और बटन, दोनों लाल रंग में फ़्लैश होते हैं.

'पेंट रेक्ट दिखाएं' चेकबॉक्स का स्क्रीनशॉट
'पेंट रेक्ट दिखाएं' चेकबॉक्स का स्क्रीनशॉट

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

डेवलपर टूल की टाइमलाइन का स्क्रीनशॉट, जिसमें लेयर को फिर से पेंट किया जा रहा है
DevTools की टाइमलाइन का स्क्रीनशॉट, जिसमें लेयर को फिर से पेंट किया जा रहा है

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

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

यह पता लगाने का सबसे अच्छा तरीका है कि क्या यह आपके किसी काम पर असर डाल रहा है. इसके लिए, Dev Tools Timeline और Show Paint Rects टूल का इस्तेमाल करें. इससे यह देखा जा सकता है कि क्या आपको अनचाहे तरीके से फिर से पेंट करना पड़ रहा है. इसके बाद, यह पता लगाने की कोशिश करें कि आपने उस रिलायआउट/रीपेंट से ठीक पहले डीओएम को कहां खराब किया है. अगर पेंटिंग करना ज़रूरी है, लेकिन इसमें बहुत ज़्यादा समय लग रहा है, तो DevTools में लगातार पेंटिंग मोड के बारे में एबरहार्ड ग्रेथर का लेख पढ़ें.

डीओएम से स्क्रीन तक: सभी चीज़ों को एक साथ जोड़ना

तो Chrome, डीओएम को स्क्रीन इमेज में कैसे बदलता है? कॉन्सेप्ट के तौर पर, यह:

  1. डीओएम को लेयर में बांटता है
  2. इनमें से हर लेयर को सॉफ़्टवेयर बिटमैप में अलग-अलग पेंट करता है
  3. उन्हें टेक्सचर के तौर पर जीपीयू पर अपलोड करता है
  4. यह अलग-अलग लेयर को एक साथ जोड़कर, स्क्रीन पर दिखने वाली फ़ाइनल इमेज बनाता है.

यह सब तब होना चाहिए, जब Chrome पहली बार किसी वेब पेज का फ़्रेम बनाता है. हालांकि, इसके बाद यह आने वाले फ़्रेम के लिए कुछ शॉर्टकट ले सकता है:

  1. अगर कुछ सीएसएस प्रॉपर्टी बदलती हैं, तो किसी भी चीज़ को फिर से पेंट करने की ज़रूरत नहीं होती. Chrome, जीपीयू पर पहले से मौजूद लेयर को फिर से कंपोज़िट कर सकता है.हालांकि, इसके लिए कंपोज़िटिंग प्रॉपर्टी अलग-अलग होनी चाहिए. जैसे, अलग-अलग पोज़िशन, अलग-अलग ओपैसिटी वगैरह.
  2. अगर किसी लेयर का कोई हिस्सा अमान्य हो जाता है, तो उसे फिर से पेंट और अपलोड किया जाता है. अगर किसी लेयर का कॉन्टेंट एक जैसा रहता है, लेकिन उसके कंपोज़िट एट्रिब्यूट बदल जाते हैं (उदाहरण के लिए, उसका अनुवाद हो जाता है या उसकी ओपैसिटी बदल जाती है), तो Chrome उसे जीपीयू पर छोड़ सकता है और नया फ़्रेम बनाने के लिए उसे फिर से कंपोज़िट कर सकता है.

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

अभी के लिए बस इतना ही. लेयर मॉडल के व्यावहारिक असर के बारे में ज़्यादा जानने के लिए, कुछ और लेख पढ़ें.

अन्य संसाधन