Aktarılabilir nesneler: Işık hızında

Chrome 13, yapılandırılmış klonlama adlı bir algoritma kullanarak bir Web İşleyici'ye/Web İşleyici'den ArrayBuffer göndermeyi kullanıma sundu. Bu sayede postMessage() API, yalnızca dize değil, File, Blob, ArrayBuffer ve JSON nesneleri gibi karmaşık türlerde mesajlar da kabul edebiliyordu. Yapılandırılmış klonlama, Firefox'un sonraki sürümlerinde de desteklenir.

Daha hızlı olmak daha iyidir

Yapılandırılmış klonlama harika olsa da yine de bir kopyalama işlemidir. 32 MB'lık bir ArrayBuffer öğesini bir çalışana aktarmanın yükü yüzlerce milisaniye olabilir. Tarayıcıların yeni sürümleri, mesaj aktarımı için Transferable Objects adlı büyük bir performans iyileştirmesi içerir.

Aktarılabilir nesnelerde veriler bir bağlamdan diğerine aktarılır. Bu yöntemde kopyalama işlemi yapılmaz. Bu sayede, bir İşleyici'ye veri gönderme performansı büyük ölçüde artar. C/C++ dünyasından geliyorsanız bunu referansla iletim olarak düşünün. Ancak referansla iletilenin aksine, çağıran bağlamdaki "sürüm" yeni bağlama aktarıldıktan sonra kullanılamaz. Örneğin, ana uygulamanızdan çalışana bir ArrayBuffer aktarırken orijinal ArrayBuffer temizlenir ve artık kullanılamaz. İçeriği, kelimenin tam anlamıyla Worker bağlamına aktarılır.

Aktarıma uygun öğelerle oynamak için postMessage()'ın aktarıma uygun nesneleri destekleyen yeni bir sürümü vardır:

worker.postMessage(arrayBuffer, [transferableList]);
window.postMessage(arrayBuffer, targetOrigin, [transferableList]);

İşçi durumunda ilk bağımsız değişken ArrayBuffer mesajıdır. İkinci bağımsız değişken, aktarılması gereken öğelerin listesidir. Bu örnekte, aktarılabilirler listesinde arrayBuffer değerini belirtirsiniz.

Karşılaştırma demosu

Aktarıma uygun öğelerin performans kazançlarını görmek için bir demo hazırladım.

Demo, postMessage() kullanarak bir çalışana 32 MB ArrayBuffer gönderip geri alır. Tarayıcınız aktarılabilir öğeleri desteklemiyorsa örnek, yapılandırılmış klonlamaya geri döner. Farklı tarayıcılarda ortalama 5 çalıştırma yaptığımda şu sonuçları elde ettim:

Yapılandırılmış klonlama ve aktarılabilir nesneler karşılaştırma tablosu

MacBook Pro/10.6.8/2, 53 GHz/Intel Core 2 Duo'da yapılandırılmış klonlama kullanılarak en hızlı FF oldu. 32 MB ArrayBuffer dosyasını bir işleyiciye gönderip ana ileti dizisine geri göndermek ortalama 302 ms sürdü (RTT - gidiş dönüş süresi). Bu, aktarılabilirlerle karşılaştırıldığında aynı testin 6,6 ms sürdüğü anlamına gelir. Bu, performansta büyük bir artış.

Bu tür hızlara sahip olmak, büyük WebGL dokularının/örgelerinin bir işleyici ile ana uygulama arasında sorunsuz bir şekilde aktarılmasına olanak tanır.

Özellik algılama

Bu durumda özellik algılama biraz zordur. Çalışanınıza küçük bir ArrayBuffer göndermenizi öneririm. Tampon aktarılırsa ancak kopyalanmazsa .byteLength değeri 0 olur:

var ab = new ArrayBuffer(1);
worker.postMessage(ab, [ab]);
if (ab.byteLength) {
    alert('Transferables are not supported in your browser!');
} else {
    // Transferables are supported.
}

Destek: Şu anda Chrome 17 ve sonraki sürümler, Firefox, Opera, Safari ve IE10 ve sonraki sürümler

Güncellendi (13.12.2011): webkitPostMessage() imzasının pencere ve işleyici için farklı olduğunu gösteren kod snippet'i. Güncellendi (03.11.2016): Tedarikçi firma ön ekleri kaldırıldı ve kod snippet'leri güncellendi