WebAssembly ile çalışırken, genellikle bir modülü indirmek, derlemek, başlatmak ve ardından JavaScript’te dışa aktardığı her şeyi kullanmak istersiniz. Bu gönderi, tam olarak bunu yapan yaygın ancak yetersiz bir kod parçacığıyla başlar, birkaç olası iyileştirmeyi tartışır ve sonunda WebAssembly’ı JavaScript’ten çalıştırmanın en basit, en verimli yolunu gösterir.
Bu kod parçacığı, yetersiz bir şekilde de olsa, tam indirme-derleme-oluşturma dansını gerçekleştirir:
Bunu kullanma!
(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);
})();
nasıl kullandığımıza dikkat edin new WebAssembly.Module(buffer)
bir yanıt arabelleğini bir modüle dönüştürmek için. Bu senkronize bir API’dir, yani ana iş parçacığını tamamlanana kadar engeller. Kullanımını caydırmak için Chrome devre dışı bırakır WebAssembly.Module
4 KB’den büyük arabellekler için. Boyut sınırı etrafında çalışmak için şunu kullanabiliriz: await WebAssembly.compile(buffer)
yerine:
(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)
dır-dir Hala optimal bir yaklaşım değil, ama buna birazdan geleceğiz.
Değiştirilen snippet’teki hemen hemen her işlem, kullanımından dolayı artık eşzamansızdır. await
netleştirir. Tek istisna new WebAssembly.Instance(module)
, Chrome’da aynı 4 KB arabellek boyutu kısıtlamasına sahiptir. Tutarlılık için ve iyiliği için ana iş parçacığını boş tutmakeşzamansız kullanabiliriz 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);
})();
hadi geri dönelim compile
Daha önce ima ettiğim optimizasyon. İle akış derlemesi, tarayıcı zaten modül baytları indirilirken WebAssembly modülünü derlemeye başlayabilir. İndirme ve derleme paralel olarak gerçekleştiği için bu, özellikle büyük yükler için daha hızlıdır.
Bu optimizasyonu etkinleştirmek için şunu kullanın: WebAssembly.compileStreaming
yerine WebAssembly.compile
. Bu değişiklik aynı zamanda ara dizi arabelleğinden kurtulmamızı sağlar, çünkü artık diziyi geçebiliriz. Response
tarafından döndürülen örnek await fetch(url)
direkt olarak.
(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);
})();
bu WebAssembly.compileStreaming
API ayrıca şu sonuca varan bir taahhüdü de kabul eder: Response
misal. Eğer ihtiyacın yoksa response
kodunuzun herhangi bir yerinde, tarafından döndürülen sözü iletebilirsiniz. fetch
doğrudan, açıkça belirtmeden await
sonucu:
(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);
})();
Eğer ihtiyacınız yoksa fetch
sonuç başka bir yerdeyse, doğrudan bile 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 kişisel olarak ayrı bir satırda tutmayı daha okunaklı buluyorum.
Yanıtı bir modülde nasıl derlediğimizi ve ardından hemen başlattığımızı gördünüz mü? Anlaşılan, WebAssembly.instantiate
tek seferde derleyebilir ve başlatabilir. bu WebAssembly.instantiateStreaming
API bunu bir akış biçiminde 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
etrafında nesne, kodu daha da basitleştirerek:
// 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 şu şekilde özetlenebilir:
- Ana ileti dizisini engellememek için eşzamansız API’ler kullanın
- WebAssembly modüllerini daha hızlı derlemek ve somutlaştırmak için akış API’lerini kullanın
- İhtiyacınız olmayan kodu yazmayın
WebAssembly ile iyi eğlenceler!