Uygulamanızın JavaScript'indeki aktif yolu WebAssembly ile değiştirme

Sürekli hızlı ilerliyor

Önceki makalelerimde, WebAssembly'nin C/C++ kitaplık ekosistemini web'e taşımanızı nasıl sağladığından bahsetmiştim. C/C++ kitaplıklarını kapsamlı şekilde kullanan bir uygulama olan squoosh, görüntüleri C++'tan WebAssembly'ye derlenmiş çeşitli codec'ler ile sıkıştırmanıza olanak tanır.

WebAssembly, .wasm dosyalarında depolanan bayt kodunu çalıştıran alt düzey bir sanal makinedir. Bu bayt kodu, ana makine sistemi için JavaScript'ten çok daha hızlı bir şekilde derlenip optimize edilebilecek şekilde güçlü bir şekilde yazılmış ve yapılandırılmıştır. WebAssembly, en başından itibaren korumalı alan kullanımına ve yerleştirmeye uygun şekilde yapılan kodların çalıştırılması için bir ortam sunar.

Deneyimlerime göre web'deki performans sorunlarının çoğunun nedeni zorunlu yerleşim ve aşırı boyamadır, ancak ara sıra bir uygulama, çok fazla zaman alan işlem yükü barındıran işler yapmak durumunda kalır. WebAssembly burada yardımcı olabilir.

Popüler Yol

Squoosh olarak, bir resim arabelleğini 90 derecenin katları döndüren bir JavaScript işlevi yazdık. OffscreenCanvas bunun için ideal olsa da hedeflediğimiz tarayıcılarda desteklenmemektedir ve Chrome'da biraz hata vardır.

Bu işlev, bir giriş görüntüsünün her pikseli üzerinde yineleme yapar ve dönüşü sağlamak için bunu çıkış resminde farklı bir konuma kopyalar. 4.094 x 4.096 piksel (16 megapiksel) bir görüntü için iç kod bloğunun 16 milyonun üzerinde iterasyonu gerekir. Buna "kısa yol" denir. Çok sayıda yinelemeye rağmen test ettiğimiz üç tarayıcıdan ikisi, işlemi 2 saniye veya daha kısa sürede tamamlıyor. Bu tür etkileşim için kabul edilebilir bir süre.

for (let d2 = d2Start; d2 >= 0 && d2 < d2Limit; d2 += d2Advance) {
    for (let d1 = d1Start; d1 >= 0 && d1 < d1Limit; d1 += d1Advance) {
    const in_idx = ((d1 * d1Multiplier) + (d2 * d2Multiplier));
    outBuffer[i] = inBuffer[in_idx];
    i += 1;
    }
}

Ancak bir tarayıcı 8 saniyeden uzun sürüyor. Tarayıcıların JavaScript'i optimize etme şekli gerçekten karmaşıktır ve farklı motorlar farklı şeyler için optimizasyon yapar. Bazıları ham yürütme için, bazıları DOM ile etkileşim için optimizasyon yapar. Bu örnekte, bir tarayıcıda optimize edilmemiş bir yola ulaştık.

Öte yandan WebAssembly, tamamen ham yürütme hızıyla geliştirilmiştir. Dolayısıyla, böyle bir kodun tüm tarayıcılarda hızlı, tahmin edilebilir performans elde etmek istiyorsak WebAssembly size yardımcı olabilir.

Tahmin edilebilir performans için WebAssembly

Genel olarak, JavaScript ve WebAssembly aynı en yüksek performansı elde edebilir. Bununla birlikte, JavaScript'te bu performansa yalnızca"hızlı yolda" ulaşılır ve bu "hızlı yolda" kalmak genellikle zordur. WebAssembly'nin sunduğu önemli avantajlardan biri, tarayıcılar arasında bile tahmin edilebilir performanstır. Katı yazma ve alt düzey mimari, derleyicinin, WebAssembly kodunun yalnızca bir kez optimize edilmesi gerekmesi ve her zaman "hızlı yolu" kullanması için daha güçlü garantiler vermesini sağlar.

WebAssembly için yazma

Daha önce C/C++ kitaplıklarını alıp web'deki işlevlerinden yararlanabilmeleri için WebAssembly'de derledik. Kitaplıkların koduna dokunmadık, tarayıcı ile kitaplık arasında bir köprü oluşturmak için yalnızca küçük miktarda C/C++ kodu yazdık. Bu sefer motivasyonumuz farklı: WebAssembly'nin sunduğu avantajlardan yararlanabilmek için WebAssembly'yi göz önünde bulundurarak sıfırdan bir şeyler yazmak istiyoruz.

WebAssembly mimarisi

WebAssembly için yazarken WebAssembly'nin gerçekte ne olduğunu biraz daha anlamanız faydalı olacaktır.

WebAssembly.org'dan alıntı yapmak için:

WebAssembly'de C veya Rust kodu derlediğinizde, modül bildirimi içeren bir .wasm dosyası alırsınız. Bu bildirim, modülün ortamından beklediği "içe aktarma işlemlerinin" listesinden, bu modülün ana makineye sağladığı dışa aktarma işlemlerinin (işlevler, sabit değerler, bellek parçaları) ve tabii ki, içerdiği işlevlere ait gerçek ikili program talimatlarından oluşur.

Bunu inceleyene kadar fark etmediğim bir şey vardı: WebAssembly'yi "yığın tabanlı bir sanal makine" haline getiren yığın, WebAssembly modüllerinin kullandığı bellek yığınında depolanmaz. Yığın tamamen sanal makine içindedir ve web geliştiricileri tarafından erişilemez (Geliştirici Araçları hariç). Bu sayede, hiçbir ek belleğe ihtiyaç duymayan WebAssembly modüllerini yazıp yalnızca sanal makine dahili yığınını kullanabilirsiniz.

Örneğimizde, görüntünün piksellerine rastgele erişime izin vermek ve bu resmin döndürülmüş bir sürümünü oluşturmak için biraz ek bellek kullanmamız gerekecek. WebAssembly.Memory tam olarak bunun için.

Bellek yönetimi

Genellikle, ek bellek kullandığınızda bu belleği bir şekilde yönetmeniz gerekir. Belleğin hangi bölümleri kullanılıyor? Hangileri ücretsiz? Örneğin C'de ardışık n baytlık bellek alanını bulan malloc(n) işlevi vardır. Bu tür işlevler "ayırıcılar" olarak da adlandırılır. Elbette kullanımdaki toplayıcının uygulanması WebAssembly modülünüze dahil edilmelidir ve bu durum dosyanızın boyutunu artırır. Bu bellek yönetimi işlevlerinin boyutu ve performansı, kullanılan algoritmaya bağlı olarak önemli ölçüde değişiklik gösterebilir. Bu nedenle, birçok dil aralarından seçim yapılabilecek birden fazla uygulama seçeneği sunar ("dmalloc", "emmalloc", "wee_alloc" vb.).

Örneğimizde, WebAssembly modülünü çalıştırmadan önce giriş resminin (ve dolayısıyla çıkış resminin boyutlarını) bildiğimizi biliyoruz. Burada bir fırsat gördük: Normalde giriş görüntüsünün RGBA arabelleğini, bir WebAssembly işlevine parametre olarak iletiyor ve döndürülen resmi, döndürülen değer olarak döndürüyoruz. Bu döndürülen değeri oluşturmak için ayırıcıdan yararlanmamız gerekir. Ancak gereken toplam bellek miktarını bildiğimiz için (giriş görüntüsünün boyutunun iki kat, giriş ve bir kez çıkış için bir kez), JavaScript kullanarak giriş resmini WebAssembly belleğine yerleştirebilir, 2. döndürülmüş bir resim oluşturmak için WebAssembly modülünü çalıştırabilir ve sonucu okumak için JavaScript'i kullanabiliriz. Hiç bellek yönetimi kullanmadan da işin başındayız.

Çok fazla seçenek yok

WebAssembly-fy için kullanmak istediğimiz orijinal JavaScript işlevine bakarsanız bunun JavaScript'e özgü API'ler içermeyen, tamamen hesaplamaya dayalı bir kod olduğunu görebilirsiniz. Dolayısıyla bu kodu herhangi bir dile taşımak oldukça kolaydır. WebAssembly'de derlenen 3 farklı dili değerlendirdik: C/C++, Rust ve AssemblyScript. Her dil için yanıtlamamız gereken tek soru şudur: Bellek yönetimi işlevlerini kullanmadan ham belleğe nasıl erişiriz?

C ve Emscripten

Emscripten, WebAssembly hedefi için bir C derleyicisidir. Emscripten'in hedefi, GCC veya clang gibi tanınmış C derleyicileri için vazgeçilmez bir alternatif olarak hizmet vermek ve çoğunlukla flag'lerle uyumludur. Bu, Emscripten'in misyonunun temel bir parçasıdır. Çünkü şirket, mevcut C ve C++ kodlarını WebAssembly'de derlemeyi mümkün olduğunca kolaylaştırmak istemektedir.

Ham belleğe erişim C'nin doğasındadır ve işaretçiler tam da bu nedenle vardır:

uint8_t* ptr = (uint8_t*)0x124;
ptr[0] = 0xFF;

Burada 0x124 sayısını, imzasız, 8 bitlik tam sayılara (veya baytlara) işaret eden bir işaretçiye dönüştürüyoruz. Bu işlem, ptr değişkenini etkili bir şekilde 0x124 bellek adresinde başlayan bir diziye dönüştürür. Bu diziyi diğer herhangi bir dizi gibi kullanabiliriz. Böylece okuma ve yazma için bağımsız baytlara erişmemize olanak tanırız. Örneğimizde, rotasyona ulaşmak için yeniden sıralamak istediğimiz bir resmin RGBA tamponuna bakıyoruz. Bir pikseli taşımak için arka arkaya 4 baytı tek seferde taşımamız gerekir (R, G, B ve A kanalları için bir bayt). Bunu kolaylaştırmak için imzasız, 32 bit tam sayılardan oluşan bir dizi oluşturabiliriz. Genellikle giriş resmimiz 4. adreste başlar ve çıkış resmimiz giriş görüntüsü bittikten hemen sonra başlar:

int bpp = 4;
int imageSize = inputWidth * inputHeight * bpp;
uint32_t* inBuffer = (uint32_t*) 4;
uint32_t* outBuffer = (uint32_t*) (inBuffer + imageSize);

for (int d2 = d2Start; d2 >= 0 && d2 < d2Limit; d2 += d2Advance) {
    for (int d1 = d1Start; d1 >= 0 && d1 < d1Limit; d1 += d1Advance) {
    int in_idx = ((d1 * d1Multiplier) + (d2 * d2Multiplier));
    outBuffer[i] = inBuffer[in_idx];
    i += 1;
    }
}

JavaScript işlevinin tamamını C'ye taşıdıktan sonra C dosyasını emcc ile derleyebiliriz:

$ emcc -O3 -s ALLOW_MEMORY_GROWTH=1 -o c.js rotate.c

Her zaman olduğu gibi, emscripten, c.js adında bir yapışkan kod dosyası ve c.wasm adlı bir wasm modülü oluşturur. Wasm modülünün gzip'le yalnızca ~260 Bayt'a ulaştığını, yapışkan kodunun ise gzip'ten sonra yaklaşık 3,5 KB olduğunu unutmayın. Biraz uğraştıktan sonra yapışkan kodu bıraktık ve vanilya API'leriyle WebAssembly modüllerini örneklendirdik. C standart kitaplığından herhangi bir şey kullanmadığınız sürece Emscripten'de bu durumla genellikle karşılaşılabilir.

Rust

Rust zengin türde bir sisteme sahip, çalışma zamanı olmayan ve bellek güvenliği ile iş parçacığı güvenliğini garanti eden bir sahiplik modeline sahip yeni ve modern bir programlama dilidir. Rust, temel bir özellik olarak WebAssembly'yi de destekler. Rust ekibi, WebAssembly ekosistemine birçok mükemmel araçla katkıda bulundu.

Bu araçlardan biri rustWasm çalışma grubu tarafından geliştirilen wasm-pack'tir. wasm-pack, kodunuzu alır ve webpack gibi paketleyicilerle kullanıma hazır olarak çalışan, web'e uygun bir modüle dönüştürür. wasm-pack son derece kullanışlı bir deneyim olsa da şu anda yalnızca Rust'ta kullanılabilir. Grup, diğer WebAssembly hedefleme dilleri için destek eklemeyi düşünüyor.

Rust'ta dilimler, C'de bulunan dizilerdir. Tıpkı C'de olduğu gibi, başlangıç adreslerimizi kullanan dilimler oluşturmamız gerekir. Bu, Rust'ın zorunlu kıldığı bellek güvenliği modeline aykırıdır. Bu nedenle, unsafe anahtar kelimesini kullanmak zorundayız. Böylece, söz konusu modele uygun olmayan kodlar yazabiliyoruz.

let imageSize = (inputWidth * inputHeight) as usize;
let inBuffer: &mut [u32];
let outBuffer: &mut [u32];
unsafe {
    inBuffer = slice::from_raw_parts_mut::<u32>(4 as *mut u32, imageSize);
    outBuffer = slice::from_raw_parts_mut::<u32>((imageSize * 4 + 4) as *mut u32, imageSize);
}

for d2 in 0..d2Limit {
    for d1 in 0..d1Limit {
    let in_idx = (d1Start + d1 * d1Advance) * d1Multiplier + (d2Start + d2 * d2Advance) * d2Multiplier;
    outBuffer[i as usize] = inBuffer[in_idx as usize];
    i += 1;
    }
}

Rust dosyalarını derleyerek

$ wasm-pack build

yaklaşık 100 bayt bir yapışkan koda sahip (her ikisi de gzip'ten sonra) 7,6 KB'lık bir wasm modülü oluşturur.

AssemblyScript

AssemblyScript, TypeScript-WebAssembly derleyicisi olmayı amaçlayan, oldukça genç bir projedir. Ancak, yalnızca herhangi bir TypeScript kullanmayacağını unutmayın. AssemblyScript, TypeScript ile aynı söz dizimini kullanır ancak kendi standart kitaplığını değiştirir. Standart kitaplığı, WebAssembly'nin özelliklerini modeller. Yani WebAssembly ile ilgili herhangi bir TypeScript'i derleyemezsiniz, ancak bu bu anlamına gelir. Sizinle WebAssembly yazmak için yeni bir programlama dili öğrenmeniz gerekmez.

    for (let d2 = d2Start; d2 >= 0 && d2 < d2Limit; d2 += d2Advance) {
      for (let d1 = d1Start; d1 >= 0 && d1 < d1Limit; d1 += d1Advance) {
        let in_idx = ((d1 * d1Multiplier) + (d2 * d2Multiplier));
        store<u32>(offset + i * 4 + 4, load<u32>(in_idx * 4 + 4));
        i += 1;
      }
    }

rotate() işlevimizin sahip olduğu küçük tür yüzeyi göz önüne alındığında, bu kodu AssemblyScript'e taşımak oldukça kolaydı. load<T>(ptr: usize) ve store<T>(ptr: usize, value: T) işlevleri, ham belleğe erişmek için AssemblyScript tarafından sağlanır. AssemblyScript dosyamızı derlemek için sadece AssemblyScript/assemblyscript npm paketini yükleyip

$ asc rotate.ts -b assemblyscript.wasm --validate -O3

AssemblyScript bize ~300 Bayt wasm modülü sağlar ancak yapışkan kodu yoktur. Modül, normal WebAssembly API'leriyle çalışır.

WebAssembly Adli Bilimleri

Rust'ın 7,6 KB boyutu, diğer 2 dille karşılaştırıldığında şaşırtıcı derecede büyük. WebAssembly ekosisteminde, WebAssembly dosyalarınızı analiz etmenize (oluşturulduğu dilden bağımsız olarak) ve size neler olduğunu bildirmenize ve ayrıca durumunuzu iyileştirmenize yardımcı olabilecek birkaç araç vardır.

Kıvrımlı

Twiggy, Rust'ın WebAssembly ekibinin kullandığı bir diğer araçtır. WebAssembly modülünden birçok analiz verisi ayıklar. Araç, Rust'a özgü değildir ve modülün çağrı grafiği gibi unsurları incelemenize, kullanılmayan veya gereksiz bölümleri belirlemenize ve hangi bölümlerin modülünüzün toplam dosya boyutuna katkıda bulunduğunu anlamanıza olanak tanır. İkincisi ise Twiggy'nin top komutuyla yapılabilir:

$ twiggy top rotate_bg.wasm
Twiggy kurulum ekran görüntüsü

Bu örnekte, dosya boyutumuzun büyük bir kısmının ayırıcıdan kaynaklandığını görebiliriz. Kodumuz dinamik ayırmaları kullanmadığı için bu şaşırtıcıydı. Katkıda bulunan bir diğer büyük faktör de "işlev adları" alt bölümüdür.

wasm şeridi

wasm-strip, WebAssembly İkili Program Araç Seti'ndeki bir araçtır veya kısaca wabt'tır. WebAssembly modüllerini incelemenize ve değiştirmenize olanak tanıyan birkaç araç içerir. wasm2wat, ikili wasm modülünü insanların okuyabileceği bir biçime dönüştüren bir sökücüdür. Wabt, okunabilir biçimi tekrar ikili wasm modülüne dönüştürmenizi sağlayan wat2wasm öğesini de içerir. WebAssembly dosyalarımızı incelemek için bu iki tamamlayıcı aracı kullansak da wasm-strip ürününün en kullanışlı araç olduğunu gördük. wasm-strip, gereksiz bölümleri ve meta verileri WebAssembly modülünden kaldırır:

$ wasm-strip rotate_bg.wasm

Bu işlem, pas modülünün dosya boyutunu 7,5 KB'tan 6,6 KB'a (gzip'ten sonra) düşürür.

wasm-opt

wasm-opt, Binaryen tarafından sunulan bir araçtır. Bir WebAssembly modülü gerekir ve modülü hem boyut hem de performans açısından yalnızca bayt koduna göre optimize etmeye çalışır. Emscripten gibi bazı araçlar bu aracı zaten çalıştırırken, bazıları çalıştırmaz. Genellikle bu araçları kullanarak ek baytlardan tasarruf etmeyi denemek iyi bir fikirdir.

wasm-opt -O3 -o rotate_bg_opt.wasm rotate_bg.wasm

wasm-opt ile bir avuç bayt daha ayıklayabiliriz ve gzip'ten sonra toplam 6,2 KB'lık bir alan bırakabiliriz.

#![no_std]

Biraz danışmanlık ve araştırmadan sonra Rust kodumuzu, Rust'un standart kitaplığını kullanmadan #![no_std] özelliğiyle yeniden yazdık. Bu işlem, dinamik bellek ayırmalarını da tamamen devre dışı bırakarak ayırıcı kodu modülümüzden kaldırır. Bu Rust dosyasını derlenen

$ rustc --target=wasm32-unknown-unknown -C opt-level=3 -o rust.wasm rotate.rs

wasm-opt, wasm-strip ve gzip'ten sonra 1,6 KB'lık wasm modülü sağladı. C ve AssemblyScript tarafından oluşturulan modüllerden hâlâ büyük olsa da hafif olarak kabul edilecek kadar küçüktür.

Performans

Yalnızca dosya boyutunu temel alan bir sonuca varmadan önce dosya boyutunu değil, performansı optimize etmek için bu yolculuğa çıktık. Peki, performansı nasıl ölçtük ve sonuçlar nelerdi?

Karşılaştırma yapma

WebAssembly düşük seviyeli bir bayt kodu biçimi olsa da ana makineye özel makine kodu oluşturmak için bir derleyici üzerinden gönderilmesi gerekir. Tıpkı JavaScript gibi derleyici de birden fazla aşamada çalışır. Basitçe ifade etmek gerekirse: İlk aşama, derleme açısından çok daha hızlıdır ancak genellikle daha yavaş kod üretir. Modül çalışmaya başladıktan sonra, tarayıcı hangi bölümlerin sık kullanıldığını gözlemler ve bunları daha iyi optimize eden ancak daha yavaş bir derleyici aracılığıyla gönderir.

Kullanım örneğimiz, bir resmi döndürme kodunun bir kez, belki iki kez kullanılması açısından ilginçtir. Dolayısıyla, çoğu durumda optimizasyon derleyicinin faydalarını hiçbir zaman elde etmeyiz. Karşılaştırma yaparken bunu göz önünde bulundurmak önemlidir. WebAssembly modüllerimizi bir döngüde 10.000 kez çalıştırmak gerçekçi olmayan sonuçlar verir. Gerçekçi sayılara ulaşmak için modülü bir kez çalıştırmalı ve tek çalıştırmada elde edilen sayılara dayanarak kararlar vermeliyiz.

Performans karşılaştırması

Dil başına hız karşılaştırması
Tarayıcı başına hız karşılaştırması

Bu iki grafik, aynı verilerin farklı görünümleridir. İlk grafikte tarayıcı başına karşılaştırma yapıyoruz, ikinci grafikte kullanılan dil başına karşılaştırma yapıyoruz. Logaritmik bir zaman ölçeği seçtiğimi lütfen unutmayın. Aynı makinede çalıştırılamayan bir tarayıcı dışında, tüm karşılaştırmaların aynı 16 megapiksel test görüntüsünü ve aynı ana makineyi kullanması da önemlidir.

Bu grafikleri çok fazla analiz etmemiş olsaydık baştaki performans sorunumuzu çözmüş olduk: Tüm WebAssembly modülleri yaklaşık 500 ms veya daha kısa bir sürede çalışıyor. Bu, başlangıçta belirlediklerimizi onaylar: WebAssembly, size tahmin edilebilir bir performans sunar. Hangi dili seçersek seçelim, tarayıcılar ve diller arasındaki fark minimum düzeydedir. Tam olarak söylemek gerekirse: JavaScript'in tüm tarayıcılardaki standart sapması yaklaşık 400 ms iken tüm WebAssembly modüllerimizin standart sapması yaklaşık 80 ms'dir.

Yapılması gerekenler

Diğer bir metrik de WebAssembly modülümüzü oluşturup squoosh ile entegre etmek için harcamanız gereken çabanın miktarı. Bu iş için sayısal bir değer atamak zordur. Bu nedenle, herhangi bir grafik oluşturmayacağım, ancak vurgulamak istediğim birkaç nokta var:

AssemblyScript sorunsuzdu. TypeScript kullanarak WebAssembly yazmak için TypeScript'i kullanmanıza olanak sağlamakla kalmaz, aynı zamanda iş arkadaşlarım için kod incelemeyi çok kolaylaştırır. Aynı zamanda iyi performansa sahip, çok küçük boyutlu ve yapıştırıcı WebAssembly modülleri hazırlar. TypeScript ekosistemindeki "şık" ve "tslint" gibi araçlar muhtemelen işe yarar.

Rust, wasm-pack ile birlikte kullanıldığında da son derece kullanışlıdır ancak daha büyük WebAssembly projelerinde daha fazla uzmandır. Bağlamalar gerekirdi ve bellek yönetimi gerekliydi. Rekabetçi bir dosya boyutuna ulaşmak için mutlu yoldan biraz uzaklaşmak zorunda kaldık.

C ve Emscripten kullanıma hazır olarak çok küçük ve yüksek performanslı bir WebAssembly modülü oluşturdu. Ancak bir kod içine alıp bunu sade ihtiyaçlara indirecek cesareti göstermeden toplam boyut (WebAssembly modülü + yapışkan kod) oldukça büyük hale geliyor.

Sonuç

O halde, bir JS etkin yolunuz varsa ve bunu WebAssembly ile daha hızlı veya tutarlı hale getirmek istiyorsanız hangi dili kullanmalısınız. Performans sorularının yanıtı, her zaman olduğu gibi duruma göre değişir. Peki ne gönderdik?

Karşılaştırma grafiği

Kullandığımız farklı dillerin modül boyutu / performans dengesi açısından bakıldığında en iyi seçeneğin C veya AssemblyScript olduğu görülmektedir. Rust'u göndermeye karar verdik. Bu kararın birden çok nedeni vardır: Şimdiye kadar Squoosh'a gönderilen tüm codec'ler Emscripten kullanılarak derlenmiştir. WebAssembly ekosistemi hakkındaki bilgimizi artırmak ve üretimde farklı bir dil kullanmak istedik. AssemblyScript güçlü bir alternatiftir, ancak proje nispeten yenidir ve derleyici, Rust derleyici kadar olgun değildir.

Rust ile diğer dillerin boyutları arasındaki fark, dağılım grafiğinde oldukça büyük olsa da aslında bu çok büyük bir konu değil: 2G üzerinden bile 500 milyar veya 1,6 KB yüklemek saniyenin 1/10'undan kısa sürer. Rust'ün yakında modül boyutu boşluğunu kapatacağını umuyorum.

Çalışma zamanı performansı açısından Rust, tarayıcılar genelinde AssemblyScript'e kıyasla daha hızlı bir ortalamaya sahiptir. Özellikle büyük projelerde Rust'ın manuel kod optimizasyonuna gerek kalmadan daha hızlı kod üretme olasılığı daha yüksektir. Ancak bu sizi en rahat olduğunuz şeyi kullanmaktan alıkoymamalıdır.

Tüm söylenmesi gereken: AssemblyScript mükemmel bir keşif oldu. Web geliştiricilerinin yeni bir dil öğrenmek zorunda kalmadan WebAssembly modülleri oluşturmalarını sağlar. AssemblyScript ekibi son derece duyarlıydı ve araç zincirini geliştirmek için aktif olarak çalışıyor. İleride kesinlikle AssemblyScript'i dikkate alacağız.

Güncelleme: Rust

Bu makaleyi yayınladıktan sonra Rust ekibinden Nick Fitzgerald, dosya boyutunu optimize etmeyle ilgili bir bölüm içeren Rust Wasm kitabına dikkat çekti. Buradaki talimatları uygulamak (özellikle bağlantı süresi optimizasyonlarını ve manuel panik işlemeyi etkinleştirmek), "normal" Rust kodu yazmamızı ve dosya boyutunu büyütmeden Cargo (Rust'un npm) özelliğini kullanmaya devam etmemizi sağladı. Rust modülü, gzip'ten sonra 370 B değerini alır. Ayrıntılar için lütfen Squoosh'ta açtığım halkla ilişkiler departmanına göz atın.

Bu yolculukta bize yardımcı oldukları için Ashley Williams, Steve Klabnik, Nick Fitzgerald ve Max Graey'e özel teşekkürlerimizi sunuyoruz.