Chrome 88'den itibaren zincirlenmiş JS zamanlayıcıların yoğun şekilde kısıtlanması

Jake Archibald
Jake Archibald

Chrome 88 (Ocak 2021), belirli koşullarda gizli sayfalar için zincirlenmiş JavaScript zamanlayıcılarını büyük ölçüde azaltacaktır. Bu işlem, CPU kullanımını azaltır ve dolayısıyla pil kullanımını da azaltır. Bunun davranışı değiştireceği bazı uç durumlar vardır ancak zamanlayıcılar genellikle farklı bir API'nin daha verimli ve daha güvenilir olacağı durumlarda kullanılır.

Tamam, bu oldukça jargon ağırlıklı ve biraz belirsizdi. Birlikte bakalım…

Terminoloji

Gizli sayfalar

Genellikle gizli, farklı bir sekmenin etkin olduğu veya pencerenin küçültüldüğü anlamına gelir ancak tarayıcılar, içeriği tamamen görünmeyen sayfaları da gizli olarak kabul edebilir. Bazı tarayıcılar bu konuda diğerlerinden daha ileri gider ancak tarayıcının görünürlüğün değiştiğini düşündüğü durumları izlemek için her zaman sayfa görünürlüğü API'sini kullanabilirsiniz.

JavaScript zamanlayıcıları

JavaScript zamanlayıcıları derken, gelecekte bir geri çağırma planlamanıza olanak tanıyan setTimeout ve setInterval'den bahsediyorum. Zamanlayıcılar kullanışlıdır ve kullanımdan kaldırılmayacaktır. Ancak bazen bir etkinliğin daha verimli ve daha doğru olacağı durumlarda durumu anlamak için kullanılırlar.

Zincirlenmiş zamanlayıcılar

setTimeout çağrısını aynı görevde setTimeout geri çağırma olarak yaparsanız ikinci çağrı "zincirlenir". setInterval ile her iterasyon zincirinin bir parçasıdır. Bu, kodla daha kolay anlaşılabilir:

let chainCount = 0;

setInterval(() => {
  chainCount++;
  console.log(`This is number ${chainCount} in the chain`);
}, 500);

Ve:

let chainCount = 0;

function setTimeoutChain() {
  setTimeout(() => {
    chainCount++;
    console.log(`This is number ${chainCount} in the chain`);
    setTimeoutChain();
  }, 500);
}

Yavaşlatma nasıl çalışır?

Yavaşlatma aşamalı olarak gerçekleşir:

Minimum kısıtlama

Bu durum, aşağıdakilerden herhangisi doğru olduğunda planlanan zamanlayıcılarda gerçekleşir:

  • Sayfa görünür olmalıdır.
  • Sayfa son 30 saniye içinde ses çıkarmıştır. Bu, ses üreten API'lerden herhangi biri olabilir ancak sessiz ses parçası sayılmaz.

İstenilen zaman aşımı 4 ms'den az ve zincir sayısı 5 veya daha fazla değilse zamanlayıcı kısıtlanmaz. Bu durumda zaman aşımı 4 ms olarak ayarlanır. Bu durum yeni değil; tarayıcılar bunu yıllardır yapıyor.

Kısıtlama

Bu durum, minimum tarama geçerli olmadığında ve aşağıdakilerden herhangisi geçerli olduğunda planlanan zamanlayıcılarda görülür:

  • Zincir sayısı 5'ten az.
  • Sayfa 5 dakikadan kısa bir süredir gizli.
  • WebRTC kullanılıyor. Daha açık belirtmek gerekirse, "açık" RTCDataChannel veya "canlı" MediaStreamTrack içeren bir RTCPeerConnection vardır.

Tarayıcı, bu gruptaki zamanlayıcıları saniyede bir kez kontrol eder. Yalnızca saniyede bir kontrol edildiğinden, benzer zaman aşımına sahip zamanlayıcılar gruplandırılır ve sekmenin kod çalıştırması için gereken süre birleştirilir. Bu da yeni bir durum değil. Tarayıcılar yıllardır bir dereceye kadar bunu yapıyor.

Yoğun kısıtlama

Tamam, Chrome 88'deki yeniliklerden bahsedeceğim. Yoğun tarama, minimum tarama veya tarama koşullarından hiçbiri geçerli olmadığında ve aşağıdaki koşulların tümü doğru olduğunda planlanan zamanlayıcılarda gerçekleşir:

  • Sayfa 5 dakikadan uzun süredir gizli.
  • Zincir sayısı 5 veya daha fazladır.
  • Sayfa en az 30 saniye boyunca sessizse
  • WebRTC kullanılmıyor.

Bu durumda tarayıcı, bu gruptaki zamanlayıcıları dakikada bir kez kontrol eder. Daha önce olduğu gibi, bu da zamanlayıcıların bu dakikalık kontrollerde birlikte gruplandırılacağı anlamına gelir.

Geçici çözümler

Zamanlayıcılar genellikle daha iyi bir alternatife sahiptir veya CPU'lara ve pil ömrüne daha az zarar vermesi için başka bir şeyle birlikte kullanılabilir.

Eyalet anketleri

Zamanlayıcıların en yaygın (yanlış) kullanımı, bir şeyin değişip değişmediğini görmek için sürekli olarak kontrol etmek veya anket yapmak için kullanılmasıdır. Çoğu durumda, bir push eşdeğeri vardır. Bu eşdeğer, değişiklik olduğunda size bildirir. Böylece, sürekli kontrol etmeniz gerekmez. Aynı sonucu sağlayan bir etkinlik olup olmadığına bakın.

Bazı örnekler:

Belirli bir zamanda bildirim göstermek isterseniz bildirim tetikleyicileri de kullanabilirsiniz.

Animasyon

Animasyon görsel bir öğe olduğundan sayfa gizliyken CPU zamanı kullanmamalıdır.

requestAnimationFrame, animasyon çalışmalarını planlama konusunda JavaScript zamanlayıcılarından çok daha iyidir. Cihazın yenileme hızıyla senkronize olur. Böylece, görüntülenebilir kare başına yalnızca bir geri çağırma alırsınız ve bu kareyi oluşturmak için maksimum süreyi elde edersiniz. Ayrıca requestAnimationFrame, sayfanın görünür olmasını bekler. Bu nedenle, sayfa gizliyken CPU kullanmaz.

Animasyonunuzun tamamını önceden belirtebiliyorsanız CSS animasyonlarını veya web animasyon API'sini kullanabilirsiniz. Bunlar requestAnimationFrame ile aynı avantajlara sahiptir ancak tarayıcı, otomatik kompozisyon gibi ek optimizasyonlar gerçekleştirebilir ve genellikle daha kolay kullanılır.

Animasyonunuzun kare hızı düşükse (ör. yanıp sönen bir imlec) zamanlayıcılar şu anda en iyi seçenektir. Ancak iki dünyanın da en iyisini elde etmek için bunları requestAnimationFrame ile birleştirebilirsiniz:

function animationInterval(ms, signal, callback) {
  const start = document.timeline.currentTime;

  function frame(time) {
    if (signal.aborted) return;
    callback(time);
    scheduleFrame(time);
  }

  function scheduleFrame(time) {
    const elapsed = time - start;
    const roundedElapsed = Math.round(elapsed / ms) * ms;
    const targetNext = start + roundedElapsed + ms;
    const delay = targetNext - performance.now();
    setTimeout(() => requestAnimationFrame(frame), delay);
  }

  scheduleFrame(start);
}

Kullanım:

const controller = new AbortController();

// Create an animation callback every second:
animationInterval(1000, controller.signal, time => {
  console.log('tick!', time);
});

// And stop it:
controller.abort();

Test

Bu değişiklik, Chrome 88'de (Ocak 2021) tüm Chrome kullanıcıları için etkinleştirilecek. Bu özellik şu anda Chrome Beta, Geliştirici ve Canary kullanıcılarının% 50'sinde etkindir. Bu özelliği test etmek istiyorsanız Chrome Beta, Dev veya Canary'ı başlatırken şu komut satırı işaretini kullanın:

--enable-features="IntensiveWakeUpThrottling:grace_period_seconds/10,OptOutZeroTimeoutTimersFromThrottling,AllowAggressiveThrottlingWithWebSocket"

grace_period_seconds/10 bağımsız değişkeni, yoğun kısıtlamanın 5 dakikanın tamamı yerine sayfa gizlendikten 10 saniye sonra etkinleşmesine neden olur. Bu sayede kısıtlamanın etkisini daha kolay görebilirsiniz.

Gelecek

Zamanlayıcılar aşırı CPU kullanımının kaynağı olduğundan, web içeriğini bozmadan bunları nasıl sınırlayabileceğimiz ve kullanım alanlarını karşılamak için hangi API'leri ekleyebileceğimiz/değiştirebileceğimiz üzerinde çalışmaya devam edeceğiz. Kişisel olarak, animationInterval ihtiyacını ortadan kaldırıp verimli, düşük frekanslı animasyon geri çağırmalarını tercih ederim. Sorunuz olursa lütfen Twitter üzerinden bana ulaşın.

Unsplash'taki Heather Zabriskie tarafından çekilen üstbilgi fotoğrafı.