Ana İş Parçacığını Engellemek Ne Zaman Mantıklı? Siber Güvenlik

Ana İş Parçacığını Engellemek Ne Zaman Mantıklı?

Ana iş parçacığını engellemek genelde kaçınılması gereken bir durumdur. Ancak, veri kopyalama maliyetinin işleme maliyetini aştığı senaryolarda, ana i

Web geliştiricilerin kutsal saydığı kurallardan biri, "ana iş parçacığını asla bloke etme" kuralıdır. Bu kural, performans kılavuzlarında sıkça vurgulanır ve genellikle iyi bir tavsiyedir. Tarayıcının ana iş parçacığı tek iş parçacıklıdır; yani aynı anda yalnızca bir iş yapabilir. Ayrıca, ana iş parçacığı yalnızca bize ait değildir; tarayıcının render motoru, giriş işleyicileri ve diğer kritik görevlerle paylaşılır. Bu nedenle, ana iş parçacığını ne kadar az meşgul edersek, uygulama o kadar duyarlı olur. Bu da bizi, UI ile hesaplama arasında kesin bir çizgi olması gerektiğine inandırarak görevleri arka plan worker'larına aktarmaya yönlendirir. Peki bu kural her zaman geçerli mi?

Victor Ayomipo, Fastary adlı ekran görüntüsü alma uzantısını geliştirirken ilginç bir durumla karşılaştı. Tüm testlerde, canvas işlemlerini Offscreen Document (Chrome uzantılarında bir arka plan işlemi) kullanmasına rağmen yaklaşık 2-3 saniyelik bir gecikme yaşadı. Oysa bir ekran görüntüsü işleminin anlık ve gecikmesiz olması beklenir. İronik bir şekilde, UI donmasını önlemek için işi ana iş parçacığından uzaklaştırma refleksi, bazen o işi taşıma (serileştirme, kopyalama ve deserileştirme) eyleminin kendisi de UI'yi dondurabiliyor. Hatta bazı durumlarda, işi arka planda yapmak, ana iş parçacığında yapmaktan daha yavaş olabiliyor.

Bu durumu anlamak için tarayıcı bağlamlarının nasıl izole edildiğini ve iletişim kurduğunu kavramak gerekir. Tarayıcı, her biri kendi bellek alanına, erişim izinlerine ve kurallara sahip birden çok ortamı aynı anda çalıştırır. Ana iş parçacığı, JavaScript mantığının çalıştığı, DOM'un yaşadığı, stillerin render edildiği ve kullanıcı etkileşimlerinin gerçekleştiği ortamdır. Web Worker'lar, DOM erişimi olmadan JavaScript çalıştırabilen ayrı iş parçacıklarıdır ve genellikle ağır veri işlemleri için kullanılır. Service Worker'lar ise ağ isteklerini yöneten ve sayfa kapalıyken bile çalışabilen proxy'lerdir. Chrome uzantılarında ise arka plan servis worker'ları, içerik script'leri ve Offscreen Document'lar gibi bağlamlar bulunur.

Bu izole ortamlar nasıl iletişim kurar? postMessage() gibi API'ler aracılığıyla açıkça mesajlaşırlar. postMessage() çağrısı, tarayıcıya bir veri parçasını alıp talep eden bağlama iletmesini söyler. Bunu yapmak için tarayıcı, Structured Clone Algorithm (SCA) adlı bir algoritmayı kullanır. SCA, JSON.stringify()'a benzer ancak çok daha güçlü ve akıllıdır. En basit haliyle, SCA derin, yinelemeli bir kopyalama işlemi, yani klonlamadır. Verilen tüm veri yapısını dolaşır, her bir değeri klonlar, taşınabilir bir formata serileştirir, bu baytları hedef bağlama gönderir ve alıcı tarafta orijinal nesneyi yeniden oluşturur.

SCA hızlıdır, en azından küçük veriler için. {theme: 'dark'} gibi küçük bir yapılandırma nesnesi için fark edilmez. Ancak büyük verilerle uğraşırken işler değişir çünkü SCA senkron, bloke edici bir O(n) işlemidir; yani maliyet veri boyutuyla doğru orantılı olarak artar. Bir kullanıcı bir düğmeye tıkladığında ve dahili olarak 8 MB'lık bir resim yükü işlenmek üzere bir arka plan worker'ına gönderildiğinde, postMessage() çağrıldığında ana iş parçacığı bu serileştirme ve kopyalama işlemini çalıştırmak için yaptığı işi hemen durdurmalıdır. Veriyi paketleme, gönderme, paketi açma ve başa dönme süresi, veriyi ana iş parçacığında işleme süresinden daha uzunsa, neden bunun yerine ana iş parçacığında yapılmasın?

Bazı geliştiriciler, Transferable Objects (ör. ArrayBuffer, ImageBitmap veya MessagePort) kullanarak Structured Clone Algorithm'ı atlatır. Transferable nesneleri aktarırken, kopya oluşturmazsınız; bunun yerine, verinin sahipliğini bir bağlamdan diğerine aktarırsınız. Bu, sıfır kopya aktarımı sağlar ve büyük veriler için idealdir. Ancak Transferable Objects'ın bir sınırlaması vardır: Nesne aktarıldıktan sonra kaynak bağlamda kullanılamaz hale gelir. Ayrıca, her veri türü Transferable değildir; yalnızca belirli türler desteklenir. Ekran görüntüsü uzantısı örneğinde, ImageBitmap kullanılabilir, ancak her durumda uygun olmayabilir.

Sonuç olarak, ana iş parçacığını bloke etme kuralı her zaman mutlak değildir. Özellikle büyük veri kopyalama maliyetinin işleme maliyetini aştığı durumlarda, ana iş parçacığında işlem yapmak daha verimli olabilir. Geliştiriciler, iş yüklerini analiz etmeli ve veri aktarım maliyetini göz önünde bulundurmalıdır. Transferable Objects gibi araçlar mevcut olsa da, her senaryo için uygun değildir. Doğru yaklaşım, kullanım durumuna göre testler yapmak ve en hızlı yolu seçmektir.

Kaynak: smashingmagazine.com

Paylaş: