Katman modeli
Giriş
Çoğu web geliştiricisi için web sayfasının temel modeli DOM'dir. Oluşturma işlemi, genellikle bir sayfanın bu gösterimini ekrandaki bir resme dönüştürme sürecidir. Modern tarayıcılar, grafik kartlarından yararlanmak için son yıllarda oluşturma işleminin çalışma şeklini değiştirdi. Bu durum, genellikle "donanım hızlandırma" olarak ifade edilir. Normal bir web sayfasından bahsederken (ör. Canvas2D veya WebGL değil), bu terimin anlamı nedir? Bu makalede, Chrome'da web içeriğinin donanım hızlandırmalı oluşturulmasının temelini oluşturan temel model açıklanmaktadır.
Büyük ve Yağlı Uyarıları
Burada WebKit'ten, özellikle de WebKit'in Chromium bağlantı noktasından bahsediyoruz. Bu makalede, web platformu özelliklerinin değil, Chrome'un uygulama ayrıntıları ele alınmaktadır. Web platformu ve standartlar, bu uygulama ayrıntılarını kodlamaz. Bu nedenle, bu makaledeki hiçbir şeyin diğer tarayıcılar için geçerli olacağının garantisi yoktur. Ancak dahili bilgiler, yine de gelişmiş hata ayıklama ve performans ayarları için yararlı olabilir.
Ayrıca, bu makalenin tamamının, Chrome'un çok hızlı değişen oluşturma mimarisinin temel bir parçasından bahsettiğini de unutmayın. Bu makalede yalnızca değişme olasılığı düşük olan hususlar ele alınmaya çalışılsa da tüm değişikliklerin altı ay içinde geçerli olacağı garanti edilmemektedir.
Chrome'da bir süredir iki farklı oluşturma yolunun olduğunu bilmeniz önemlidir: donanım hızlandırmalı yol ve eski yazılım yolu. Bu yazının hazırlandığı an itibarıyla tüm sayfalar Windows, ChromeOS ve Android için Chrome'da donanım hızlandırmalı yoluna gitmektedir. Mac ve Linux'ta yalnızca bazı içeriklerinin birleştirilmesi gereken sayfalar hızlandırılmış bir yolda ilerler (nelerin birleştirmeyi gerektireceği hakkında daha fazla bilgiyi aşağıda bulabilirsiniz). Ancak kısa süre içinde tüm sayfalar bu hızda çalışmaya başlayacaktır.
Son olarak, oluşturma motorunun özelliklerine göz atıyoruz ve performans üzerinde büyük etkisi olan özelliklerini inceleyeceğiz. Kendi sitenizin performansını artırmaya çalışırken katman modelini anlamanız yararlı olabilir. Ancak katman modelini anlamanız da çok kolaydır: Katmanlar kullanışlı yapılardır, ancak çok sayıda katman oluşturmak grafik yığınının geneli için ek yüke neden olabilir. Kendinizi önceden uyarmış olun.
DOM'den Ekrana
Katmanlar ile Tanışın
Bir sayfa yüklenip ayrıştırıldıktan sonra, tarayıcıda birçok web geliştiricisinin aşina olduğu bir yapı olarak temsil edilir: DOM. Ancak bir sayfayı oluştururken tarayıcıda doğrudan geliştiricilere sunulmayan bir dizi ara gösterim olur. Bu yapılardan en önemlisi katmandır.
Chrome'da aslında birkaç farklı katman türü vardır: DOM'nin alt ağaçlarından sorumlu RenderKatmanlar ve RenderKatmans'ın alt ağaçlarından sorumlu olan GraphicsKatmanlar. Burada ikincisi en çok ilgi çekici olanıdır, çünkü GraphicsKatmanlar GPU'ya doku olarak yüklenen öğelerdir. Bundan böyle GraphicsKatman'ı kastetmek için "katman" diyeceğim.
GPU terminolojisini bir kenara bırakın: Doku nedir? Bunu, ana bellekten (yani RAM) video belleğine (GPU'nuzda VRAM) taşınan bir bit eşlem görüntüsü olarak düşünebilirsiniz. GPU'ya başladıktan sonra bunu bir örgü geometrisiyle eşleyebilirsiniz. Video oyunlarında veya CAD programlarında bu teknik, iskeletsel 3D modellere "deri" vermek için kullanılır. Chrome, web sayfası içeriği parçalarını GPU'ya aktarmak için dokuları kullanır. Dokular, gerçekten basit bir dikdörtgen ağa uygulanarak farklı konumlara ve dönüşümlere ucuz bir şekilde eşlenebilir. 3D CSS bu şekilde çalışır ve hızlı kaydırma için de mükemmeldir. Ancak daha sonra bunların her ikisi hakkında da daha fazla bilgi edineceksiniz.
Katman kavramını açıklamak için birkaç örneğe göz atalım.
Chrome'daki katmanları incelerken çok yararlı bir araç, Geliştirici Araçları'ndaki "oluşturma" başlığı altında bulunan "birleştirilmiş katman kenarlıklarını göster" işaretidir (ör. küçük dişli simgesi). Katmanların ekranda nerede olduğunu vurgular. Haydi etkinleştirelim. Bu ekran görüntüleri ve örneklerin tümü, bu yazının yapıldığı tarihte en son Chrome Canary olan Chrome 27'den alınmıştır.
Şekil 1: Tek katmanlı sayfa
<!doctype html>
<html>
<body>
<div>I am a strange root.</div>
</body>
</html>
Bu sayfada yalnızca tek bir katman var. Mavi tablo karoları temsil eder. Bunlar, Chrome'un bir defada GPU'ya büyük bir katmanın parçalarını yüklemek için kullandığı katmanın alt birimleri olarak düşünülebilir. Bunlar burada pek önemli değildir.
Şekil 2: Kendi katmanındaki bir öğe
<!doctype html>
<html>
<body>
<div style="transform: rotateY(30deg) rotateX(-30deg); width: 200px;">
I am a strange root.
</div>
</body>
</html>
<div>
bölümüne onu döndüren bir 3D CSS özelliği yerleştirerek bir öğenin kendi katmanına sahip olduğunda nasıl göründüğünü görebiliriz: Bu görünümde bir katmanı ana hatlarıyla belirten turuncu kenarlığa dikkat edin.
Katman Oluşturma Kriterleri
Başka neler kendi katmanına sahip? Chrome'un buradaki buluşsal yöntemleri zaman içinde gelişti ve değişmeye devam ediyor. Ancak, şu anda aşağıdaki tetikleyici katman oluşturma yöntemlerinden herhangi biri:
- 3D veya perspektif dönüştürme CSS özellikleri
- Hızlandırılmış video kod çözmeyi kullanan
<video>
öğe - 3D (WebGL) içeriğe veya hızlandırılmış 2D içeriğe sahip
<canvas>
öğeleri - Birleşik eklentiler (ör. Flash)
- Opaklıkları için CSS animasyonlu veya animasyonlu dönüşüm kullanan öğeler
- Hızlandırılmış CSS filtreleri içeren öğeler
- Öğenin birleştirme katmanına sahip bir alt öğesi var (diğer bir deyişle, öğenin kendi katmanında bir alt öğesi varsa)
- Öğenin, birleştirme katmanına sahip düşük z-endeksine sahip bir eşdüzesi var (diğer bir deyişle, birleştirilmiş bir katman üzerinde oluşturulmuştur)
Pratik Çıkarımlar: Animasyon
Katmanları da hareket ettirebildiğimiz için animasyon için çok kullanışlı hale getirebiliriz.
Ş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ğinin yerini değiştirmek için çok kullanışlıdır. Temel durumda Chrome, bir katmanın içeriğini doku olarak GPU'ya yüklemeden önce bir yazılım bit eşlemine boyar. Bu içerik gelecekte değişmezse yeniden boyanmasına gerek yoktur. Bu İyi Bir Şeydir: Yeniden boyama işlemi, JavaScript çalıştırmak gibi başka işlere harcanabilecek zaman alır ve boyanın uzun sürmesi animasyonlarda aksamalara veya gecikmelere neden olur.
Örneğin, Geliştirici Araçları zaman çizelgesinin şu görünümüne bakın: Bu katman ileri geri dönerken boyama işlemi yapılmaz.
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 genişler. Bu, tüm öğenin (bu örnekte tüm katman) yeniden düzenlenmesine ve yeniden boyanmasına neden olur.
Nelerin boyandığını görmenin iyi bir yolu, Geliştirici Araçları'ndaki "Oluşturma" başlığının altında bulunan "Boya Rektörlerini Göster" aracını kullanmaktır. Bu özelliği açtıktan sonra, düğme tıklandığında animasyonlu öğe ve düğmenin kırmızı renkte yanıp söndüğüne dikkat edin.
Boyama etkinlikleri, Geliştirici Araçları zaman çizelgesinde de gösterilir. Keskin gözlere sahip okuyucular, orada iki boyama etkinliği olduğunu fark edebilir: Biri katman için, diğeri düğmenin kendisi için. Düğmenin basılı duruma gelmesi/basılı durumdan çıkarken yeniden boyanması.
Chrome'un her zaman tüm katmanı yeniden boyaması gerekmediğini unutmayın. DOM'un yalnızca geçersiz kılınan kısmını yeniden boyamak için akıllı davranmaya çalışır. Bu örnekte, değiştirdiğimiz DOM öğesi tüm katmanın boyutudur. Ancak diğer birçok durumda, bir katmanda çok sayıda DOM öğesi bulunur.
Bir sonraki soru, geçersiz kılmaya neden olup yeniden boyamaya zorlayanlardır. Geçersiz kılmaları zorlayabilecek çok sayıda uç durum olduğundan bunu kapsamlı bir şekilde yanıtlamak zordur. En yaygın neden, CSS stillerini değiştirerek veya geçişe yol açarak DOM'nin kirlenmesidir. Tony Gentilcore'un geçişin nedenleri hakkında harika bir blog yayını var. Stoyan Stefanov da resim konusunu daha ayrıntılı olarak ele alan bir makale hazırladı (ancak bu makale sadece boyamayla bitmiş, bu süslü kompozisyonla ilgili bir kısmı yoktur).
Bunun üzerinde çalıştığınız şeyi etkileyip etkilemediğini anlamanın en iyi yolu, Geliştirici Araçları Zaman Çizelgesi'ni ve Boyama Dikdörtgenlerini Göster araçlarını kullanmaktır. Bunu yaparken istemediğiniz zamanlarda yeniden boyayıp çizemediğinizi kontrol edebilir, ardından geçişten/yeniden boyamadan hemen önce DOM'yi nereye kirlettiğinizi belirlemeye çalışın. Resim yapmak kaçınılmazsa ancak makul derecede uzun sürüyorsa Geliştirici Araçları'ndaki sürekli boyama moduyla ilgili Eberhard Gräther'in makalesine göz atın.
Bir araya getirme: DOM'den Ekrana
Peki Chrome, DOM'yi nasıl ekran görüntüsüne dönüştürür? Kavramsal olarak:
- DOM'yi alır ve katmanlara ayırır
- Bu katmanların her birini bağımsız olarak yazılım bit eşlemlerine boyar
- Bu öğeleri doku olarak GPU'ya yükler
- Çeşitli katmanları birleştirerek son ekran görüntüsü haline getirir.
Tüm bunların, Chrome bir web sayfasının çerçevesini ilk kez oluşturduğunda gerçekleşmesi gerekir. Ancak gelecekteki kareler için bazı kısayollar gerekebilir:
- Belirli CSS özellikleri değişirse herhangi bir şeyi yeniden boyamanız gerekmez. Chrome sadece zaten GPU'da bulunan mevcut katmanları doku olarak, ancak farklı birleştirme özellikleriyle (ör.farklı konumlarda, farklı opaklıklarda vb.) yeniden derleyebilir.
- Bir katmanın bir kısmı geçersiz kılınırsa bu katman 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, içeriği GPU'da bırakabilir ve yeni bir kare oluşturmak için yeniden birleştirebilir.
Açıkça anlaşılacağı üzere, katman tabanlı birleştirme modelinin oluşturma performansı üzerinde derin etkileri vardır. Birleştirme, hiçbir şeyin boyanmaması gerektiğinde nispeten ucuzdur. Bu nedenle, oluşturma performansında hata ayıklamaya çalışırken katmanların yeniden boyanmasını önlemek genel olarak iyi bir hedeftir. Tecrübeli geliştiriciler, yukarıdaki birleştirme tetikleyicileri listesine bakacak ve kolayca katman oluşturulmasının mümkün olduğunu fark edecektir. Ancak bunları oluştururken göz ardı etmeyin. Çünkü bunlar boş değildir: Sistem RAM'inde ve GPU'da bellek kaplar (özellikle mobil cihazlarda sınırlıdır) ve çok fazla olması, mantık açısından hangisinin görünür olduğunun takip edilmesine neden olabilir. Birçok katman, katmanların büyük olması ve daha önce gerçekleşmedikleri yerde çok fazla çakışması durumunda pikselleştirme için harcanan zamanı da artırabilir. Bu durum, bazen "fazla çizim" olarak da bilinir. Bu duruma yol açabilir. Bu nedenle, bilginizi akıllıca kullanın!
Şimdilik hepsi bu. Katman modelinin pratik uygulamalarıyla ilgili birkaç makale daha için takipte kalın.