Chrome'da Hızlandırılmış Oluşturma

Katman modeli

Tom Wiltzius
Tom Wiltzius

Giriş

Çoğu web geliştiricisi için bir web sayfasının temel modeli DOM'dur. Oluşturma, genellikle bir sayfanın bu temsilini ekranda bir resme dönüştürme işlemidir. Modern tarayıcılar, grafik kartlarından yararlanmak için son yıllarda oluşturma işleminin işleyiş şeklini değiştirdi. Bu durum genellikle "donanım hızlandırması" olarak adlandırılır. Normal bir web sayfasından (Canvas2D veya WebGL değil) bahsederken bu terim aslında ne anlama gelir? Bu makalede, Chrome'da web içeriğinin donanım hızlandırmalı oluşturma işleminin temelini oluşturan temel model açıklanmaktadır.

Büyük, Yağlı Uyarılar

Burada WebKit'ten, daha da spesifik olarak WebKit'in Chromium bağlantısından bahsediyoruz. Bu makalede, web platformu özellikleri değil, Chrome'un uygulama ayrıntıları ele alınmaktadır. Web platformu ve standartları bu düzeyde uygulama ayrıntılarını kodlamaz. Bu nedenle, bu makaledeki herhangi bir şeyin diğer tarayıcılar için geçerli olacağı garanti edilmez. Yine de dahili bilgiler, gelişmiş hata ayıklama ve performans ayarı için yararlı olabilir.

Ayrıca, bu makalenin tamamında Chrome'un oluşturma mimarisinin çok hızlı değişen temel bir parçasının ele alındığını unutmayın. Bu makalede, yalnızca değişme olasılığı düşük olan konular ele alınmaya çalışılmıştır. Ancak bu bilgilerin altı ay sonra da geçerli olacağı garanti edilmez.

Chrome'un bir süredir iki farklı oluşturma yoluna sahip olduğunu bilmek önemlidir: donanım hızlandırmalı yol ve eski yazılım yolu. Bu makalenin yazıldığı tarih itibarıyla tüm sayfalar Windows, ChromeOS ve Android için Chrome'da donanım hızlandırmalı yola yönlendirilmektedir. Mac ve Linux'ta yalnızca içeriklerinin bir kısmı için birleştirmeye ihtiyaç duyan sayfalar hızlandırılmış yoldan geçer (nelerin birleştirmeye ihtiyaç duyacağı hakkında daha fazla bilgi için aşağıya bakın). Ancak yakında tüm sayfalar da hızlandırılmış yoldan geçecektir.

Son olarak, oluşturma motorunun içine bakıyor ve performans üzerinde büyük etkisi olan özelliklerine göz atıyoruz. Kendi sitenizin performansını artırmaya çalışırken katman modelini anlamak yararlı olabilir ancak kendinize zarar vermeniz de kolaydır: Katmanlar yararlı yapılardır ancak çok fazla katman oluşturmak grafik yığınında ek yük oluşturabilir. Bu konuda şimdiden uyarılmış olduğunuzu hatırlatmak isteriz.

DOM'dan Ekrana

Katmanlar ile tanışın

Bir sayfa yüklendikten ve ayrıştırıldıktan sonra tarayıcıda birçok web geliştiricisinin aşina olduğu bir yapı olarak gösterilir: DOM. Ancak tarayıcı, bir sayfayı oluştururken doğrudan geliştiricilere gösterilmeyen bir dizi ara temsile sahiptir. Bu yapılardan en önemlisi katmandır.

Chrome'da aslında birkaç farklı katman türü vardır: DOM alt ağaçlarından sorumlu olan RenderLayers ve RenderLayers alt ağaçlarından sorumlu olan GraphicsLayers. GPU'ya doku olarak yüklenen GraphicsLayers olduğundan, burada en ilginç olan ikinci seçenektir. Bundan sonra GraphicsLayer için "katman" ifadesini kullanacağım.

GPU terminolojisiyle ilgili kısa bir bilgi: Doku nedir? Ana bellekten (ör. RAM) video belleğine (ör. GPU'nuzdaki VRAM) taşınan bir bitmap resim olarak düşünebilirsiniz. GPU'ya aktarılan bu verileri bir ağ geometrisiyle eşleyebilirsiniz. Video oyunlarında veya CAD programlarında bu teknik, iskelet 3D modellere "deri" vermek için kullanılır. Chrome, web sayfası içeriğinin parçalarını GPU'ya aktarmak için dokuları kullanır. Dokular, gerçekten basit bir dikdörtgen örgeye uygulanarak farklı konumlara ve dönüşümlere uygun şekilde düşük maliyetle eşlenebilir. 3D CSS bu şekilde çalışır ve hızlı kaydırma için de mükemmeldir. Ancak bu iki konu hakkında daha sonra daha fazla bilgi vereceğiz.

Katman kavramını açıklamak için birkaç örneğe göz atalım.

Chrome'da katmanları incelerken çok faydalı bir araç, Dev Tools'daki "oluşturma" başlığı altındaki ayarlarda (yani küçük dişli simgesi) bulunan "birleştirilmiş katman kenarlarını göster" işaretçisidir. Katmanların ekrandaki konumunu basit bir şekilde vurgular. Şimdi açalım. Bu ekran görüntülerinin ve örneklerin tümü, bu makalenin yazıldığı sıradaki en son Chrome Canary sürümünden (Chrome 27) alınmıştır.

Şekil 1: Tek katmanlı sayfa

<!doctype html>
<html>
<body>
  <div>I am a strange root.</div>
</body>
</html>
Sayfanın temel katmanı etrafında birleştirilmiş katman oluşturma kenarlıkları ekran görüntüsü
Sayfanın temel katmanı etrafındaki birleştirilmiş katman oluşturma kenarlıkları ekran görüntüsü

Bu sayfada yalnızca bir katman vardır. Mavi ızgara, karoları temsil eder. Karoları, Chrome'un büyük bir katmanın bölümlerini tek seferde GPU'ya yüklemek için kullandığı katmanın alt birimleri olarak düşünebilirsiniz. Burada çok önemli değiller.

Şekil 2: Kendi katmanında bir öğe

<!doctype html>
<html>
<body>
  <div style="transform: rotateY(30deg) rotateX(-30deg); width: 200px;">
    I am a strange root.
  </div>
</body>
</html>
Döndürülen katmanın oluşturma sınırlarının ekran görüntüsü
Döndürülen katmanın oluşturma kenarlarının ekran görüntüsü

<div> öğesine döndürme işlemi yapan bir 3D CSS özelliği ekleyerek bir öğenin kendi katmanını aldığında nasıl göründüğünü görebiliriz: Bu görünümde bir katmanın ana hatlarını gösteren turuncu kenarlığa dikkat edin.

Katman Oluşturma Ölçütleri

Başka hangi öğeler kendi katmanına sahiptir? Chrome'un buradaki sezgisel kuralları zaman içinde gelişti ve gelişmeye devam ediyor. Ancak şu anda aşağıdakilerden herhangi biri katman oluşturmayı tetikler:

  • 3D veya perspektif dönüştürme CSS özellikleri
  • Hızlandırılmış video kod çözme özelliğini kullanan <video> öğeleri
  • 3D (WebGL) bağlamı veya hızlandırılmış 2D bağlamı olan <canvas> öğeleri
  • Birleştirilmiş eklentiler (ör. Flash)
  • Opaklık için CSS animasyonu olan veya animasyonlu dönüşüm kullanan öğeler
  • Hızlandırılmış CSS filtreleri içeren öğeler
  • Öğe, bir kompozisyon katmanı içeren bir alt öğeye sahiptir (yani öğenin kendi katmanında bulunan bir alt öğesi varsa)
  • Öğenin, birleştirme katmanı (yani birleştirilmiş bir katmanın üzerinde oluşturulur) içeren, daha düşük z-endeksi olan bir kardeşi var.

Pratik Yansımaları: Animasyon

Katmanları da taşıyabiliriz. Bu da katmanları animasyon için çok faydalı hale getirir.

Şekil 3: Animasyonlu Katmanlar

<!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>

Daha önce de belirtildiği gibi, katmanlar, statik web içeriği arasında gezinmek için çok kullanışlıdır. Temel durumda Chrome, bir katmanın içeriğini GPU'ya doku olarak yüklemeden önce yazılım bitmap'ine boyar. Bu içerik gelecekte değişmezse yeniden boyanmasına gerek yoktur. Bu iyi bir şeydir: Yeniden boyama işlemi, JavaScript çalıştırmak gibi diğer işlemler için kullanılabilecek zaman alır ve boya uzunsa animasyonlarda takılmalara veya gecikmelere neden olur.

Örneğin, Dev Tools zaman çizelgesinin bu görünümüne bakın: Bu katman ileri geri dönerken boyama işlemi yoktur.

Animasyon sırasında Dev Tools zaman çizelgesinin ekran görüntüsü
Animasyon sırasında DevTools zaman çizelgesinin ekran görüntüsü

Geçersiz. Yeniden boyama

Ancak katmanın içeriği değişirse yeniden boyanması gerekir.

Şekil 4: Katmanları Yeniden Boyama

<!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>

Giriş öğesi her tıklandığında dönen öğe 1 piksel daha geniş olur. Bu, öğenin tamamının (bu durumda bir katmanın tamamı) yeniden düzenlenmesine ve yeniden boyanmasına neden olur.

Nelerin boyandığını görmek için Dev Tools'daki "boya dikdörtgenlerini göster" aracını kullanabilirsiniz. Bu araç, Dev Tools ayarlarının "Oluşturma" başlığı altında da bulunur. Etkinleştirdikten sonra, düğme tıklandığında animasyonlu öğenin ve düğmenin kırmızı renkte yanıp söndüğünü fark edin.

Boyama karelerini göster onay kutusunun ekran görüntüsü
Boya dikdörtgenlerini göster onay kutusunun ekran görüntüsü

Boyama etkinlikleri, Geliştirici Araçları zaman çizelgesinde de gösterilir. Dikkatli okuyucular burada iki boyama etkinliği olduğunu fark edebilir: biri katman için, diğeri de düğmenin kendisi içindir. Düğme basılı duruma geçtiğinde/basılı durumdan çıktığında yeniden boyanır.

Geliştirici Araçları Zaman Çizelgesi&#39;nde bir katmanın yeniden boyanmasını gösteren ekran görüntüsü
DevTools zaman çizelgesinin bir katmanı yeniden boyadığını gösteren ekran görüntüsü

Chrome'un her zaman katmanın tamamını yeniden boyaması gerekmez. Chrome, DOM'un yalnızca geçersiz kılınan bölümünü yeniden boyamak için akıllı olmaya çalışır. Bu durumda, değiştirdiğimiz DOM öğesi, katmanın tamamının boyutudur. Ancak diğer birçok durumda, bir katmanda çok sayıda DOM öğesi bulunur.

Bu noktada, geçersiz kılma işleminin nedenini ve yeniden boyamaya zorlamanın ne olduğunu merak edebilirsiniz. Geçersiz kılma işlemini zorunlu kılacak birçok uç durum olduğu için bu sorunun kapsamlı bir şekilde yanıtlanması zordur. En yaygın neden, CSS stillerini değiştirerek veya yeniden düzenlemeye neden olarak DOM'u kirletmektir. Tony Gentilcore'un yeniden düzenlemeye neyin neden olduğuyla ilgili harika bir blog yayını, Stoyan Stefanov'un ise boyamayı daha ayrıntılı olarak ele alan bir makalesi var (ancak bu makale, bu süslü kompozisyon işlerinden ziyade boyamayı ele alıyor).

Bunun üzerinde çalıştığınız bir şeyi etkileyip etkilemediğini öğrenmenin en iyi yolu, Dev Tools Zaman Çizelgesi ve Boyama Dikdörtgenlerini Göster araçlarını kullanarak istemediğiniz halde yeniden boyama yapıp yapmadığınızı görmek ve ardından yeniden düzenleme/yeniden boyama işleminden hemen önce DOM'u nerede kirlettiğinizi belirlemeye çalışmaktır. Boyama işlemi kaçınılmazsa ancak makul olmayan bir süre alıyorsa Dev Tools'daki sürekli boyama modu hakkında Eberhard Gräther'in makalesine göz atın.

Birleştirme: DOM'den ekrana

Peki Chrome, DOM'u nasıl ekran görüntüsüne dönüştürüyor? Kavramsal olarak:

  1. DOM'u alıp katmanlara böler
  2. Bu katmanların her birini bağımsız olarak yazılım bitmap'lerine boyar
  3. Bunları GPU'ya doku olarak yükler.
  4. Çeşitli katmanları nihai ekran resminde birleştirir.

Tüm bunların, Chrome bir web sayfasının çerçevesini ilk kez oluşturduğunda gerçekleşmesi gerekir. Ancak sonraki kareler için bazı kısayollar kullanabilirsiniz:

  1. Belirli CSS özellikleri değişirse hiçbir şeyi yeniden boyamanız gerekmez. Chrome, GPU'da bulunan mevcut katmanları doku olarak yeniden oluşturabilir ancak farklı oluşturma özellikleriyle (ör.farklı konumlarda, farklı opaklıklarda vb.) oluşturabilir.
  2. Bir katmanın bir kısmı geçersiz hale gelirse yeniden boyanır ve yeniden yüklenir. İçeriği aynı kalır ancak birleştirilmiş özellikleri değişirse (ör. çevrilir veya opaklığı değişirse) Chrome, GPU'da bırakıp yeni bir kare oluşturmak için yeniden birleştirebilir.

Katman tabanlı kompozisyon modelinin oluşturma performansı üzerinde derin etkileri olduğu artık açıktır. Hiçbir şeyin boyanması gerekmediğinde, birleştirme işlemi nispeten ucuzdur. Bu nedenle, oluşturma performansında hata ayıklama işlemi yaparken katmanların yeniden boyanmasını önlemek genel olarak iyi bir hedeftir. Tecrübeli geliştiriciler, yukarıdaki oluşturma tetikleyicilerinin listesine göz atarak katman oluşturmayı kolayca zorlayabileceklerini fark eder. Ancak, ücretsiz olmadıkları için bunları körü körüne oluşturmamaya dikkat edin: Sistem RAM'inde ve GPU'da (özellikle mobil cihazlarda sınırlı) bellek kaplarlar ve çok sayıda oluşturulmaları, hangilerinin görünür olduğunu takip eden mantıkta başka ek maliyetlere neden olabilir. Çok sayıda katman, büyükse ve daha önce örtüşmediği yerlerde çok fazla örtüşüyorsa rasterleştirme işleminin süresini uzatabilir. Bu da bazen "aşırı çizim" olarak adlandırılan duruma yol açar. Bu nedenle, bilginizi akıllıca kullanın.

Şimdilik bu kadar. Katman modelinin pratik sonuçlarıyla ilgili birkaç makale daha yayınlayacağız.

Ek Kaynaklar