Tarayıcılar JavaScript zamanlayıcılarını neden throttle ediyor?
(nolanlawson.com)- JavaScript’te
setTimeout(0)gerçekte anında çalışmaz; çoğu durumda en az 4 ms gecikmeyle çalışır ve bu, kötüye kullanımı önlemek için tarayıcıların koyduğu temel bir sınırlamadır - Bu kısıtlar, web sitelerinin zamanlayıcıları ölçüsüzce kullanarak pil tüketimine veya etkileşim kalitesinin düşmesine yol açmasını önlemek içindir; pil modunda 16 ms’ye, arka plan sekmelerinde ise 1 saniyeye kadar daha sıkı sınırlar uygulanabilir
- Geliştiriciler,
setTimeoutsınırlamalarını aşmak içinsetImmediate,MessageChannel.postMessage,window.postMessage,scheduler.postTaskgibi çeşitli alternatif zamanlayıcı API’lerini kullanagelmiştir - Gerçek benchmark sonuçlarına göre Chrome ve Firefox’ta 4 ms clamping uygulanırken
MessageChannelvescheduler.postTaskneredeyse gecikmesiz çalışır; Safari isesetTimeoutüzerinde daha agresif kısıtlamalar uygular - Temelde konu, kullanıcı deneyimini koruma ile geliştirici özgürlüğü arasındaki denge meselesidir; bugün Scheduler API standartlaşmış çözüm olarak öne çıksa da, kötüye kullanım olursa yeni tarayıcı müdahaleleri (intervention) gündeme gelebilir
setTimeout kısıtının arka planı
setTimeout(0)olsa bile kötüye kullanım nedeniyle gerçek çalıştırma çoğu zaman en az 4 ms sonra gerçekleşirconst start = performance.now() setTimeout(() => { // yaklaşık 4 ms sonra çalışır console.log(performance.now() - start) }, 0)- Amaç, kontrolsüz yinelenen çağrıları engelleyerek pil tüketimini ve render gecikmesini azaltmaktır
- Bazı tarayıcılar ortama göre bu sınırı daha da sıkılaştırır
- Pil modu: eski Edge’de 16 ms
- Arka plan sekmesi: Chrome’da 1 saniyeye kadar gecikme
Diğer zamanlayıcı API’lerinin ortaya çıkışı
setImmediate: yalnızca IE ve eski Edge’de desteklenir, fiilen terk edilmiştirMessageChannel.postMessage: ayrı bir kanal üzerinden event loop’a iş iletirwindow.postMessage: performansı iyidir ama diğer script’lerle çakışma riski vardırscheduler.postTask: modern tarayıcılarda desteklenir ve en istikrarlı seçenek olarak değerlendirilir
Benchmark sonuçları (MacBook Pro 2021, 101 tekrar ölçümü)
- Chrome 139:
setTimeout4.2 ms,scheduler.postTask0 ms - Firefox 142:
setTimeout4.72 ms,scheduler.postTask0.01 ms - Safari 18.4:
setTimeout26.73 ms,MessageChannel0.52 ms,window.postMessage0.05 ms
fake-indexeddb vakası
- IndexedDB, event loop’taki microtask’lar biter bitmez transaction’ın otomatik commit edilmesini ister
- Node.js’teki
setImmediateidealdir, ancak tarayıcılardasetTimeoutverimsiz kalır - Chrome’da 300 ms süren bir işin tarayıcıda 4.8 saniyeye kadar uzaması sorunu ortaya çıkmıştır
- Çözüm olarak varsayılan tercih
scheduler.postTaskoldu; uyumluluk için deMessageChannel/window.postMessagefallback olarak benimsendi
Tarayıcı müdahalesi tartışması
- Bir görüşe göre zamanlayıcılar sınırlandırılmalıdır; ancak bu sayede geliştiriciler kendilerini kendi hatalarına karşı koruyabilir
- Diğer görüş ise geliştiricilere ölçüm yapıp optimizasyon uygulayabilecekleri özgürlüğün tanınması gerektiğini savunur
- Sonuçta tarayıcılar, kullanıcı önceliği ilkesi doğrultusunda kötüye kullanımı önlemek için müdahale eder
- Scheduler API, bu iki yaklaşım arasında uzlaşma sunar; geliştiricilere ayrıntılı görev kontrolü verirken tarayıcının render pipeline’ıyla uyumlu olacak şekilde tasarlanmıştır
Geleceğe bakış
postTaskvepostMessagebir süre daha throttle edilmeden kalacak gibi görünüyor- Ancak
user-blockinggibi yüksek önceliklerin kötüye kullanılması durumunda yeniden müdahale gündeme gelebilir - Uzun vadede
scheduler2benzeri başka bir alternatif API’ye ihtiyaç duyulabilir
Henüz yorum yok.