WebAssembly ile çalışırken genellikle bir modül indirmek, derlemek, örneklendirmek ve ardından JavaScript'te dışa aktardığını kullanmak istersiniz. Bu yayında, optimum verimlilik için önerdiğimiz yaklaşım açıklanmaktadır.
WebAssembly ile çalışırken genellikle bir modül indirmek, derlemek, örneklendirmek ve daha sonra, JavaScript'e aktardığı şeyi kullanabilirsiniz. Bu gönderi, yaygın ancak ideal olmayan bir kodla başlıyor snippet'inin tam olarak bunu yaptığına dikkat edin, çeşitli olası optimizasyonları tartışır ve en sonunda WebAssembly'yi JavaScript'ten çalıştırmanın en basit ve en verimli yolunu sunar.
Bu kod snippet'i, indirme işlemlerini anında yapmak için gereken dansı mükemmel olmasa da mükemmel olmayan bir şekilde çalışır:
Bunu kullanmayın.
(async () => {
const response = await fetch('fibonacci.wasm');
const buffer = await response.arrayBuffer();
const module = new WebAssembly.Module(buffer);
const instance = new WebAssembly.Instance(module);
const result = instance.exports.fibonacci(42);
console.log(result);
})();
Bir yanıt arabelleğini modüle dönüştürmek için new WebAssembly.Module(buffer)
yöntemini nasıl kullandığımıza dikkat edin. Bu,
eşzamanlı API'dir. Diğer bir deyişle, tamamlanana kadar ana iş parçacığını engeller. Chrome, kullanılmasını önlemek için
4 KB'tan büyük arabellekler için WebAssembly.Module
öğesini devre dışı bırakır. Boyut sınırını aşmak için
bunun yerine await WebAssembly.compile(buffer)
kullanın:
(async () => {
const response = await fetch('fibonacci.wasm');
const buffer = await response.arrayBuffer();
const module = await WebAssembly.compile(buffer);
const instance = new WebAssembly.Instance(module);
const result = instance.exports.fibonacci(42);
console.log(result);
})();
await WebAssembly.compile(buffer)
, hala ideal yaklaşım olmasa da bunu bir şekilde ele alacağız.
tıklayın.
Değiştirilen snippet'teki hemen hemen her işlem artık eşzamansız olduğundan, await
kullanımı
açık. Tek istisna, aynı 4 KB arabelleğine sahip olan new WebAssembly.Instance(module)
.
Chrome'da boyut kısıtlaması var. Tutarlılık için ve ana ileti dizisini korumak amacıyla
ücretsiz olarak ayarlayabiliriz.
WebAssembly.instantiate(module)
.
(async () => {
const response = await fetch('fibonacci.wasm');
const buffer = await response.arrayBuffer();
const module = await WebAssembly.compile(buffer);
const instance = await WebAssembly.instantiate(module);
const result = instance.exports.fibonacci(42);
console.log(result);
})();
Daha önce ipucu verdiğim compile
optimizasyonuna geri dönelim. Akışlı
bir derleme olarak sunuyorsanız, tarayıcı zaten
modül baytları indirilmeye devam ederken WebAssembly modülünü derlemeye başlar. İndirildikten sonra
Bu süreç, özellikle büyük yüklerde daha hızlı yapılır.
Bu optimizasyonu etkinleştirmek için WebAssembly.compile
yerine WebAssembly.compileStreaming
politikasını kullanın.
Bu değişiklik, ara dizi tamponundan da kurtulmamızı sağlar. Çünkü artık
Response
örneği doğrudan await fetch(url)
tarafından döndürüldü.
(async () => {
const response = await fetch('fibonacci.wasm');
const module = await WebAssembly.compileStreaming(response);
const instance = await WebAssembly.instantiate(module);
const result = instance.exports.fibonacci(42);
console.log(result);
})();
WebAssembly.compileStreaming
API, Response
ile çözümlenen bir taahhüdü de kabul eder.
kullanır. Kodunuzda başka bir yerde response
öğesine ihtiyaç duymuyorsanız verdiğiniz sözü iletebilirsiniz
sonucu açık bir şekilde await
vermeden, doğrudan fetch
tarafından döndürülür:
(async () => {
const fetchPromise = fetch('fibonacci.wasm');
const module = await WebAssembly.compileStreaming(fetchPromise);
const instance = await WebAssembly.instantiate(module);
const result = instance.exports.fibonacci(42);
console.log(result);
})();
fetch
sonucuna başka bir yerde ihtiyacınız yoksa doğrudan iletebilirsiniz:
(async () => {
const module = await WebAssembly.compileStreaming(
fetch('fibonacci.wasm'));
const instance = await WebAssembly.instantiate(module);
const result = instance.exports.fibonacci(42);
console.log(result);
})();
Yine de bunu ayrı bir satırda tutmak adına daha okunabilir olduğunu düşünüyorum.
Yanıtı nasıl modül halinde derlediğimizi ve ardından hemen nasıl örneklendirdiğimizi öğrenin. Sonuçta
WebAssembly.instantiate
tek seferde derleyip örnek verebilir. İlgili içeriği oluşturmak için kullanılan
WebAssembly.instantiateStreaming
API, bunu akış şeklinde yapar:
(async () => {
const fetchPromise = fetch('fibonacci.wasm');
const { module, instance } = await WebAssembly.instantiateStreaming(fetchPromise);
// To create a new instance later:
const otherInstance = await WebAssembly.instantiate(module);
const result = instance.exports.fibonacci(42);
console.log(result);
})();
Yalnızca tek bir örneğe ihtiyacınız varsa module
nesnesini saklamanın bir anlamı yoktur.
kodunu daha da basitleştirin:
// This is our recommended way of loading WebAssembly.
(async () => {
const fetchPromise = fetch('fibonacci.wasm');
const { instance } = await WebAssembly.instantiateStreaming(fetchPromise);
const result = instance.exports.fibonacci(42);
console.log(result);
})();
Uyguladığımız optimizasyonlar aşağıdaki gibi özetlenebilir:
- Ana iş parçacığını engellememek için eşzamansız API'ler kullanın
- WebAssembly modüllerini daha hızlı derlemek ve örneklendirmek için akış API'lerini kullanın.
- İhtiyacınız olmayan kodları yazmayın
WebAssembly ile eğlenin!