İçeriğe geç
academia.sh

Ders 02 / 27

Kritik Oluşturma Yolu

İlk boyamanın beklemek zorunda olduğu kaynaklar; çizimi engelleyen biçem ile ayrıştırmayı engelleyen betiğin ayrımı, gidiş-dönüş sayısının hesaplanması ve engellemeyi kaldıran yazımlar.

İçindekiler

Önceki ders ölçütleri tanımladı: en büyük içerik boyası geç gerçekleşiyorsa bir sorun vardır. Gecikmenin üç kaynağı olabilir — sunucunun yanıtı üretmesi, yanıtın taşınması ve tarayıcının ekrana bir şey çizebilmek için beklemek zorunda olduğu kaynaklar. Üçüncüsü tümüyle geliştiricinin denetimindedir.

Bu ders o bekleyişi tanımlar. Kritik oluşturma yolu (critical rendering path), ilk boyamanın gerçekleşebilmesi için tamamlanması zorunlu olan işler zinciridir. Zincirin uzunluğu ölçülebilir ve kısaltılabilir.

İki Farklı Engelleme

Tarayıcı belgeyi yukarıdan aşağı ayrıştırır ve yol boyunca karşılaştığı kaynakları ister. İki tür kaynak bu akışı durdurur ve ikisi farklı biçimde durdurur.

Çizimi engelleyen biçem. Bir dış biçem dosyası indirilip çözümlenmeden tarayıcı hiçbir şey çizmez. Gerekçesi basamaklamadır: CSS ile Görsel Sunum kursunda kurulan kurala göre bir ögenin hesaplanmış değeri, henüz inmemiş bir dosyadaki bildirimle değişebilir. Eksik biçemle çizmek, saniyeler sonra bambaşka görünen bir sayfa demektir. Tarayıcı bu yüzden bekler. Belgenin ayrıştırılması sürer — biçem dosyası ayrıştırmayı durdurmaz — ama boyama durur.

Ayrıştırmayı engelleyen betik. Belge içine yazılmış, defer ya da async taşımayan bir betik, indirilip çalıştırılana kadar ayrıştırmayı durdurur. Gerekçesi betiğin belgeyi değiştirebilmesidir: betik, kendisinden sonraki içeriği üretebilir ya da silebilir, bu yüzden tarayıcı devam edemez. Ayrıştırma durduğu için ondan sonrası keşfedilemez; boyama da zaten olamaz.

İki engelleme birleşir. Betikten önce gelen bir biçem dosyası, betiğin çalışmasını da bekletir: betik hesaplanmış değerleri okuyabileceği için tarayıcı biçemin çözümlenmesini beklemek zorundadır. Böylece tek bir sıralama kararı üç işi birbirine bağlar.

Üç Değişken

Bekleyişin uzunluğu üç ayrı büyüklüğe bağlıdır ve bunları ayırmak, hangi eniyilemenin işe yarayacağını belirler.

Bayt sayısı bant genişliğine bağlı olan bölümdür. Sıkıştırma ve ölü kod eleme buraya etki eder.

Gidiş-dönüş sayısı gecikmeye bağlı olan bölümdür. Bir bağlantı üzerinde veri gönderilirken tıkanıklık penceresi baştan küçüktür ve her turda büyür; bu yüzden büyük bir dosya tek turda gelmez. Ağ Modelleri ve Protokoller kursunda tanımlanan bu davranış, başarım açısından şu sonucu doğurur: ilk baytlar ucuz, sonrakiler pahalıdır.

Zincir derinliği ise keşif sırasına bağlıdır. Bir kaynağın varlığı ancak başka bir kaynak indirildikten sonra öğreniliyorsa, ikisi koşut istenemez; süreleri toplanır.

Aşağıdaki model üçünü birlikte hesaplar.

// kritik-yol.mjs — ilk boyanin kac gidis-donuse mal oldugunu modelleyen hesap

const MSS = 1460;               // bayt: tek segmentin tasidigi veri
const BASLANGIC_PENCERESI = 10; // segment: ilk turda gonderilebilen segment sayisi

// Baglanti, tikaniklik penceresini turlar boyunca tasir; pencere her turda ikiye katlanir.
function baglanti() {
  let pencere = BASLANGIC_PENCERESI;
  return {
    get pencere() { return pencere; },
    // Bir asama: es zamanli istenen kaynaklar ayni pencereyi paylasir.
    asama(baytlar) {
      let kalan = baytlar.reduce((a, b) => a + b, 0);
      let tur = 0;
      do {
        kalan -= pencere * MSS;
        pencere *= 2;
        tur += 1;
      } while (kalan > 0);
      return tur;
    },
  };
}

function ilkBoya(senaryo) {
  const b = baglanti();
  let tur = senaryo.baglantiKurulumu;
  const dokum = [["baglanti kurulumu", senaryo.baglantiKurulumu, "-"]];
  for (const asama of senaryo.asamalar) {
    const oncekiPencere = b.pencere;
    const t = b.asama(asama.baytlar);
    tur += t;
    dokum.push([asama.ad, t, `${oncekiPencere} -> ${b.pencere} segment`]);
  }
  return { tur, dokum };
}

// Kuzey Yamac Olcum Istasyonu — istasyon listesi sayfasi.
// Baglanti kurulumu: ad cozumleme 1 + tasima el sikismasi 1 + guvenli el sikisma 1 = 3 tur.
const senaryolar = [
  {
    ad: "A: engelleyen bicem ve betik basta",
    baglantiKurulumu: 3,
    asamalar: [
      { ad: "HTML govdesi", baytlar: [18_400] },
      { ad: "engelleyen bicem + betik", baytlar: [62_000, 141_000] },
      { ad: "betigin kesfettigi bicem", baytlar: [24_000] },
    ],
  },
  {
    ad: "B: betik ertelendi",
    baglantiKurulumu: 3,
    asamalar: [
      { ad: "HTML govdesi", baytlar: [18_400] },
      { ad: "engelleyen bicem", baytlar: [62_000] },
    ],
  },
  {
    ad: "C: kritik bicem gomuldu",
    baglantiKurulumu: 3,
    asamalar: [
      { ad: "HTML govdesi (+ gomulu bicem)", baytlar: [18_400 + 9_800] },
    ],
  },
];

console.log("--- yavas baslangic: k. tur sonunda gonderilebilmis toplam bayt ---");
let birikim = 0;
let pencere = BASLANGIC_PENCERESI;
for (let k = 1; k <= 4; k++) {
  birikim += pencere * MSS;
  console.log(`${k}. tur  pencere ${String(pencere).padStart(3)} segment  toplam ${String(birikim).padStart(7)} bayt`);
  pencere *= 2;
}

console.log("\n--- ilk boyaya kadar gidis-donus dokumu ---");
const sonuclar = [];
for (const s of senaryolar) {
  const r = ilkBoya(s);
  sonuclar.push({ ad: s.ad, tur: r.tur });
  console.log(`\n${s.ad}`);
  for (const [ad, t, p] of r.dokum) {
    console.log(`  ${ad.padEnd(30)} ${t} tur   ${p}`);
  }
  console.log(`  ${"TOPLAM".padEnd(30)} ${r.tur} tur`);
}

console.log("\n--- senaryolarin karsilastirmasi ---");
const taban = sonuclar[0].tur;
for (const s of sonuclar) {
  console.log(`${s.ad.padEnd(34)} ${String(s.tur).padStart(2)} tur   A'ya oran: ${(s.tur / taban).toFixed(2)}`);
}
--- yavas baslangic: k. tur sonunda gonderilebilmis toplam bayt ---
1. tur  pencere  10 segment  toplam   14600 bayt
2. tur  pencere  20 segment  toplam   43800 bayt
3. tur  pencere  40 segment  toplam  102200 bayt
4. tur  pencere  80 segment  toplam  219000 bayt

--- ilk boyaya kadar gidis-donus dokumu ---

A: engelleyen bicem ve betik basta
  baglanti kurulumu              3 tur   -
  HTML govdesi                   2 tur   10 -> 40 segment
  engelleyen bicem + betik       3 tur   40 -> 320 segment
  betigin kesfettigi bicem       1 tur   320 -> 640 segment
  TOPLAM                         9 tur

B: betik ertelendi
  baglanti kurulumu              3 tur   -
  HTML govdesi                   2 tur   10 -> 40 segment
  engelleyen bicem               2 tur   40 -> 160 segment
  TOPLAM                         7 tur

C: kritik bicem gomuldu
  baglanti kurulumu              3 tur   -
  HTML govdesi (+ gomulu bicem)  2 tur   10 -> 40 segment
  TOPLAM                         5 tur

--- senaryolarin karsilastirmasi ---
A: engelleyen bicem ve betik basta  9 tur   A'ya oran: 1.00
B: betik ertelendi                  7 tur   A'ya oran: 0.78
C: kritik bicem gomuldu             5 tur   A'ya oran: 0.56

İlk tablo tıkanıklık penceresinin büyümesini gösteriyor: ilk turda on dört kilobaytın biraz üzerinde veri gönderilebiliyor, dördüncü turun sonunda iki yüz kilobaytı aşıyor. Bu sayı bir sınır değil, bir başlangıç varsayımıdır; başlangıç penceresi yapılandırmaya bağlıdır ve model değeri en başta bir sabit olarak açıyor.

Üç senaryo aynı sayfayı üç ayrı yazımla kuruyor. A senaryosunda engelleyen biçem ve betik belgenin başında duruyor, üstelik betik indirildikten sonra ikinci bir biçem dosyası keşfediliyor. B senaryosunda betik erteleniyor; hem kendi baytları hem de keşfettiği zincir kritik yoldan çıkıyor. C senaryosunda ilk ekranın biçemi belgenin içine gömülüyor ve dış istek kalmıyor.

Sonuç oranlarla okunur: B senaryosu A’nın yüzde yetmiş sekizi, C senaryosu yüzde elli altısı kadar bekliyor. Mutlak süre verilemez, çünkü tur süresi ağa bağlıdır — ama tur sayısı yazımın kendisinden çıkar ve karşılaştırılabilir.

Model iki noktada gerçeği sadeleştirir. Aşamalar içindeki koşut isteklerin aynı pencereyi paylaştığını varsayar ve pencerenin boşta kalma sonrası küçülmesini hesaba katmaz. İkisi de sonucu B ve C lehine değil, A lehine kaydırır; yani gerçek fark modelin gösterdiğinden küçük değil, büyüktür.

Engellemeyi Kaldırmak

Kritik yolu kısaltmanın yolları, engellemenin iki türüne karşılık gelir.

Betiği kritik yoldan çıkarmak. defer bildirimi, betiğin ayrıştırmaya koşut indirilmesini ve belge ayrıştırması bittikten sonra, yazıldığı sırayla çalıştırılmasını sağlar. async da koşut indirir ama indiği anda çalıştırır; sıra garantisi yoktur ve çalıştığı an ayrıştırmayı yine keser. Birbirine bağımlı betikler için defer, bağımsız ve tek başına çalışan betikler için async uygundur. Modül olarak yüklenen betikler öntanımlı olarak ertelenmiş davranır.

Biçemi koşullu hâle getirmek. Bir biçem bağlantısına media özniteliği yazıldığında, koşul o anda tutmuyorsa dosya çizimi engellemez. Yazdırma biçemleri ve yalnızca geniş ekranlarda geçerli biçemler bu yolla kritik yoldan çıkarılır. Dosya yine indirilir, ancak düşük öncelikle ve boyamayı bekletmeden.

Kritik biçemi gömmek. İlk ekranı çizmeye yeten bildirimler belgenin içine yazılır; kalan biçem engellemeyen bir yolla yüklenir. Bu, C senaryosundaki kazancın kaynağıdır ve bedeli vardır: gömülü biçem ayrı önbelleklenemez, her sayfa isteğiyle yeniden gelir ve belgeyi büyütür. Karar, tekrar ziyaret oranına bağlıdır — ilk ziyaretin ağırlıklı olduğu bir sayfada kazanç, her gün açılan bir panelde kayıptır.

Geç keşfedilen kaynağı öne çekmek. Bir kaynak ancak biçem çözümlendikten ya da betik çalıştıktan sonra keşfediliyorsa, preload bildirimiyle belge başında istenebilir. Bu bildirim bir eniyileme değil, bir düzeltmedir: zinciri kısaltmanın doğrudan yolu varken kullanılmamalıdır, çünkü yanlış yazıldığında kaynağı iki kez indirtir ya da gerçekten kritik olan bir kaynağın bant genişliğini alır.

Keşif Zinciri

A senaryosundaki dördüncü satır — “betiğin keşfettiği biçem” — tek başına bir turdan fazla maliyet üretir, çünkü o tur ancak betik indirilip çalıştıktan sonra başlayabilir.

Tarayıcının ön tarayıcısı belgeyi ayrıştırmadan önce hızlıca gözden geçirir ve gördüğü kaynakları erkenden ister. Ön tarayıcının göremediği tek şey, belgede yazılı olmayan kaynaklardır: betik tarafından eklenen bağlantılar, biçem dosyası içinden çağrılan başka biçemler, bir yapılandırma dosyası okunduktan sonra belirlenen adresler.

Bu yüzden kritik yol eniyilemesinin en etkili adımı çoğu zaman bayt azaltmak değil, zinciri düzleştirmektir: kritik kaynakların hepsinin belgenin ilk baytlarında görünür olması.

İstasyon Listesi Sayfasının Belge Başı

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Kuzey Yamaç Ölçüm İstasyonu — İstasyonlar</title>

  <!-- ilk ekranın biçemi: gömülü, dış istek yok -->
  <style>
    .istasyon-listesi { display: grid; gap: 12px; }
    .istasyon-listesi > li { min-height: 72px; }
  </style>

  <!-- kalan biçem: çizimi engellemez, indikten sonra uygulanır -->
  <link rel="stylesheet" href="/varlik/istasyon.9f2c1a.css" media="print"
        onload="this.media='all'">
  <noscript><link rel="stylesheet" href="/varlik/istasyon.9f2c1a.css"></noscript>

  <!-- yazdırma biçemi hiçbir zaman çizimi engellemez -->
  <link rel="stylesheet" href="/varlik/yazdirma.3ce8b0.css" media="print">

  <!-- uygulama betiği: ayrıştırmaya koşut iner, ayrıştırma bitince sırayla çalışır -->
  <script src="/varlik/giris.4a1c.js" defer></script>
</head>

İkinci bağlantı bir yazım hilesidir ve açıklanması gerekir: media="print" yazılan bir biçem çizimi engellemez, dosya indikten sonra onload işleyicisi ortamı all yaparak biçemi uygular. noscript içindeki ikinci bağlantı, betik çalışmadığında biçemin yine de gelmesini sağlar. Hile, biçem bağlantısı için doğrudan bir “engelleme” bildirimi bulunmamasından doğar.

Gömülü biçemdeki min-height bildirimi başarım değil kararlılık içindir: liste satırları veri gelmeden önce yüksekliklerini alır ve önceki derste hesaplanan düzen kayması oluşmaz. İki hedef aynı bildirimde buluşur.

Özet

  • Kritik oluşturma yolu, ilk boyamanın beklemek zorunda olduğu işler zinciridir; çizimi engelleyen biçem boyamayı, ayrıştırmayı engelleyen betik hem ayrıştırmayı hem boyamayı durdurur.
  • Bekleyişin üç bileşeni ayrı ayrı ele alınır: bayt sayısı bant genişliğine, gidiş-dönüş sayısı gecikmeye, zincir derinliği keşif sırasına bağlıdır.
  • Tıkanıklık penceresi turlarla büyüdüğü için ilk baytlar ucuzdur; bir kaynağı kritik yoldan çıkarmak, onu küçültmekten çok daha büyük kazanç verebilir.
  • defer, async ve media bildirimleri engellemeyi kaldırır; kritik biçemi gömmek dış isteği tümüyle siler ama önbelleklenebilirlikten vazgeçer.
  • Ön tarayıcı yalnızca belgede yazılı kaynakları görür; zinciri düzleştirmek çoğu zaman bayt azaltmaktan etkilidir.

Sonraki Adım

Kritik yol kısaldığında ilk boyama erkene çeker, ama en büyük içerik boyası çoğu sayfada bir metin bloğu değil bir görseldir. İstasyon listesindeki kart görselleri ve ölçüm ayrıntısı sayfasındaki istasyon fotoğrafı, belgeden çok daha fazla bayt taşır; yazı tipi dosyaları ise metnin ne zaman okunabilir olacağını belirler. İkisinin de kendi boyut, biçim ve yükleme kararları vardır. Sonraki ders bu kararları ele alır ve hangi aday dosyanın hangi koşulda indirileceğini hesaplar.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat