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

Hep hızlı gidiyorsunuz,

Önceki makalelerimde, WebAssembly'nin C/C++ kitaplık ekosistemini web'e taşımanıza nasıl olanak tanıdığından bahsetmiştim. squoosh, C/C++ kitaplıklarının kapsamlı şekilde kullanılmasını sağlayan uygulamalardan biridir. Resimleri, C++'tan WebAssembly'ye kadar derlenen çeşitli codec'lerle sıkıştırmanızı sağlayan web uygulamamızdı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ılır ve yapılandırılır. WebAssembly, en başından beri korumalı alan ve yerleştirmenin dikkate alındığı kodları çalıştırmak için bir ortam sağlar.

Tecrübelerime göre, web'deki performans sorunlarının çoğunun zorunlu düzen ve aşırı boyama nedeniyle ortaya çıktığını ancak uygulamaların zaman zaman çok fazla zaman alan hesaplama açısından pahalı bir iş yapması gerektiğini düşünüyorum. WebAssembly size bu konuda yardımcı olabilir.

Popüler Yol

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

Bu işlev, giriş resminin her pikseli üzerinde yinelenir ve döndürmeyi sağlamak için bunu çıkış resminde farklı bir konuma kopyalar. 4.094x4.096 piksel bir resim (16 megapiksel) için iç kod bloğunun 16 milyonun üzerinde yinelemesi gerekir, buna "kısa yol" deriz. Çok sayıda yineleme olmasına rağmen, test ettiğimiz üç tarayıcıdan ikisi görevi 2 saniye veya daha kısa sürede bitiriyor. 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 yol bulmuştur.

WebAssembly ise tamamen ham yürütme hızına göre geliştirilmiştir. Dolayısıyla, bunun gibi kodlar için tarayıcılarda hızlı, tahmin edilebilir bir 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ı sağlayabilir. Ancak, JavaScript için bu performansa yalnızca "hızlı yolda" ulaşılabilir ve bu "hızlı yolda" kalmak genellikle yanıltıcı olur. WebAssembly'nin sunduğu temel avantajlardan biri, tarayıcılar arasında bile öngörülebilir performans sağlamasıdır. Sıkı yazma ve düşük düzey mimari, derleyicinin daha güçlü garantiler vermesini sağlar. Böylece WebAssembly kodu yalnızca bir kez optimize edilir ve her zaman "hızlı yolu" kullanır.

WebAssembly için yazma

Daha önce, web'deki işlevlerini kullanmak için C/C++ kitaplıklarını alıp WebAssembly'de derledik. Kitaplıkların koduna gerçekten dokunmadık, tarayıcı ve kitaplık arasında köprü oluşturmak için küçük miktarlarda C/C++ kodu yazdık. Bu sefer motivasyonumuz farklı: WebAssembly'yi düşünerek sıfırdan bir şeyler yazmak istiyoruz ve böylece WebAssembly'nin sahip olduğu avantajlardan yararlanabildik.

WebAssembly mimarisi

for WebAssembly için yazarken WebAssembly'nin aslında ne olduğunu biraz daha iyi anlamak faydalıdır.

WebAssembly.org adresinden alıntı yapmak için:

Bir C veya Rust kodu parçasını WebAssembly'de derlediğinizde modül bildirimi içeren bir .wasm dosyası elde edersiniz. Bu beyan; modülün, ortamından beklediği "içe aktarmaların" listesi, bu modülün ana makine için kullanılabilir hale getirdiği dışa aktarmaların bir listesi (işlevler, sabit değerler, bellek parçaları) ve tabii ki içerdikleri işlevler için gerçek ikili talimatlardan oluşur.

Bunu inceleyene kadar fark etmediğim bir şey var: WebAssembly'yi "yığın tabanlı bir sanal makine" yapan yığın, WebAssembly modüllerinin kullandığı bellek yığınında depolanmaz. Yığın, tamamen sanal makine içindedir ve web geliştiricilerinin erişimine kapalıdır (DevTools üzerinden olmayan). Bu nedenle, ek belleğe ihtiyaç duymayan WebAssembly modüllerini yazmak ve yalnızca sanal makine dahili yığınını kullanmak mümkündür.

Örneğimizde, resmimizin piksellerine rastgele erişim sağlamak ve bu resmin döndürülmüş bir sürümünü oluşturmak için ek bellek kullanmamız gerekecek. WebAssembly.Memory bunun için kullanılır.

Bellek yönetimi

Genellikle, ek bellek kullandığınızda bu belleği bir şekilde yönetmeniz gerekir. Belleğin hangi kısımları kullanılıyor? Hangileri ücretsizdir? Örneğin C'de, art arda n baytlık bir bellek alanı bulan malloc(n) işleviniz vardır. Bu tür işlevler "ayrıcılar" olarak da adlandırılır. Kullanımdaki ayırıcının uygulanması WebAssembly modülünüze dahil edilmelidir. Bu, 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, ("dmalloc", "emmalloc", "wee_alloc" vb.) birden fazla uygulama seçeneği sunar.

Örneğimizde, WebAssembly modülünü çalıştırmadan önce giriş resminin boyutlarını (ve dolayısıyla, çıktı resminin boyutlarını) biliyoruz. Burada bir fırsat gördük: Geleneksel olarak, bir WebAssembly işlevine parametre olarak giriş resminin RGBA arabelleğini iletir ve döndürülen görüntüyü döndürme değeri olarak döndürürdik. Döndürülen bu değeri oluşturmak için ayırıcıdan yararlanmamız gerekir. Ancak gereken toplam bellek miktarını bildiğimizden (giriş için bir kez ve çıkış için birer kez giriş resminin boyutunun iki katı) giriş resmini JavaScript kullanarak WebAssembly belleğine yerleştirebilir, 2. bir döndürülmüş resim oluşturmak için WebAssembly modülünü çalıştırabilir ve ardından sonucu okumak için JavaScript'i kullanabiliriz. Herhangi bir bellek yönetimi kullanmadan da kurtulabiliriz.

Seçimi bozulmuş

WebAssembly-fy'sini istediğimiz orijinal JavaScript işlevine bakarsanız bunun JavaScript'e özel API'leri olmayan, tamamen hesaplamaya dayalı bir kod olduğunu görebilirsiniz. Dolayısıyla, bu kodu herhangi bir dile taşımak oldukça basit olmalıdı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önetim işlevlerini kullanmadan ham belleğe nasıl erişiyoruz?

C ve Emscripten

Emscripten, WebAssembly hedefi için bir C derleyicisidir. Emscripten'ın amacı, GCC veya clang gibi iyi bilinen C derleyicileri için açılır menü işlevi görmektir ve çoğunlukla işaretlerle uyumludur. Mevcut C ve C++ kodlarını WebAssembly'de derlemeyi mümkün olduğunca kolaylaştırmak istediği için bu, Emscripten'ın misyonunun temel bir parçasıdır.

Ham belleğe erişmek C'nin doğasında vardı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 bit tam sayılara (veya baytlara) işaret eden bir işaretçiye dönüştürüyoruz. Bu işlem, ptr değişkenini etkin bir şekilde 0x124 bellek adresinde başlayan bir diziye dönüştürür. Bu diziyi başka herhangi bir dizi gibi kullanabiliriz. Böylece, okuma ve yazma için baytlara ayrı ayrı erişebiliriz. Örneğimizde, rotasyon elde etmek için yeniden sıralamak istediğimiz bir resmin RGBA tamponuna bakıyoruz. Bir pikseli taşımak için aslında aynı anda 4 ardışık baytı taşımamız gerekir (her kanal için bir bayt: R, G, B ve A). Bunu kolaylaştırmak için imzasız 32 bit tam sayılardan oluşan bir dizi oluşturabiliriz. Kural olarak, giriş resmimiz 4. adreste ve çıkış resmimiz, giriş resmi 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ıştırıcı kodu dosyası ve c.wasm adlı bir wasm modülü oluşturur. Wasm modülünün gzip olarak yalnızca yaklaşık 260 Bayt olduğunu, yapışkan kodunun gzip sonrasında ise yaklaşık 3,5 KB olduğunu unutmayın. Biraz uğraşmanın ardından yapışkan kodu bırakıp WebAssembly modüllerini vanilla API'lerle örneklendirabildik. Bu işlem, C standart kitaplığından hiçbir şey kullanmadığınız sürece Emscripten ile mümkündür.

Rust

Rust; zengin tür sistemi, çalışma zamanı olmayan ve bellek güvenliğini ve 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 de rustwasm çalışma grubunun sunduğu wasm-pack'tir. wasm-pack, kodunuzu alır ve webpack gibi paketleyicilerle kullanıma hazır, web dostu 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ılabilmektedir. Grup, diğer WebAssembly hedefleme dilleri için destek eklemeyi düşünüyor.

Rust'ta dilimler, C'deki dizileri ifade eder. Tıpkı C'de olduğu gibi, başlangıç adreslerimizi kullanan dilimler oluşturmamız gerekir. Bu, Rust'ın uyguladığı bellek güvenliği modeline aykırıdır. Bu nedenle, işimizi halletmek için unsafe anahtar kelimesini kullanmamız ve bu modele uygun olmayan kod yazmamıza olanak tanımamız gerekir.

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ı derleme ve

$ wasm-pack build

yaklaşık 100 baytlık bir yapışkan kod içeren 7,6 KB'lık bir wasm modülü verir (her ikisi de gzip'ten sonra).

AssemblyScript

AssemblyScript, TypeScript'ten WebAssembly derleyicisi olmayı amaçlayan oldukça yeni bir projedir. Bununla birlikte, yalnızca TypeScript'i kullanmadığını unutmamak önemlidir. AssemblyScript, TypeScript ile aynı söz dizimini kullanır ancak standart kitaplığı kendi kitaplığı için değiştirir. Standart kitaplıklar, WebAssembly'nin özelliklerini modeller. Yani WebAssembly'de kullandığınız TypeScript'i yalnızca derleyemezsiniz. Bu, WebAssembly'yi yazmak için yeni bir programlama dili öğrenmek zorunda olmadığınız anlamına gelir.

    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 düşünüldüğünde, 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 yalnızca AssemblyScript/assemblyscript npm paketini yükleyip çalıştırmamız gerekir

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

AssemblyScript, bize yaklaşık 300 baytlık atık modülü sağlayacak ve yapışkan kodu olmayacaktır. Modül yalnızca vanilla WebAssembly API'leriyle çalışır.

WebAssembly Adli Bilişim

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ı (oluşturulan dilden bağımsız olarak) analiz etmenize, ne olup bittiğini anlatıp durumunuzu iyileştirmenize yardımcı olabilecek birkaç araç vardır.

Dalgalı

Twiggy, Rust'ın WebAssembly ekibinin WebAssembly modülünden ayrıntılı bilgiler içeren bir grup veri ayıklayan bir diğer aracıdır. Araç Rust'a özel değildir ve modülün çağrı grafiği gibi şeyleri incelemenize, kullanılmayan veya gereksiz bölümleri belirlemenize ve modülünüzün toplam dosya boyutuna katkıda bulunan bölümlerin hangileri olduğunu belirlemenize olanak tanır. İkincisi, 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. Kodumuzda dinamik ayırma kullanmadığı için bu şaşırtıcıydı. Katkıda bulunan diğer bir önemli faktör de "işlev adları" alt bölümüdür.

Wasm-Strip

wasm-strip, WebAssembly İkili Program Seti'nden bir araçtır. WebAssembly modüllerini incelemenize ve değiştirmenize olanak tanıyan birkaç araç içerir. wasm2wat, ikili wasm modülünü insanlar tarafından okunabilir 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 içerir. WebAssembly dosyalarımızı incelemek için bu iki tamamlayıcı aracı kullandık, ancak en faydalı aracın wasm-strip 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, 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ü alır ve bunu yalnızca bayt koduna dayanarak hem boyut hem de performans için optimize etmeye çalışır. Emscripten gibi bazı araçlar bu aracı zaten çalıştırırken diğerleri çalıştırmaz. Genellikle bu araçları kullanarak ek bayt kaydetmek iyi bir fikirdir.

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

wasm-opt ile bir avuç baytı daha kırparak gzip'ten sonra toplam 6,2 KB'lık bir kısım bırakabiliriz.

#![no_std]

Biraz danışma ve araştırma yaptıktan sonra, Rust'ın standart kitaplığını kullanmadan ve #![no_std] özelliğini kullanarak Rust kodumuzu yeniden yazdık. Bu da dinamik bellek ayırmalarını tamamen devre dışı bırakarak ayırıcı kodunu modülümüzden kaldırır. Bu Rust dosyasını

$ 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 daha büyük olsa da, hafif olarak kabul edilecek kadar küçüktür.

Performans

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

Karşılaştırma nasıl yapılır?

WebAssembly düşük seviyeli bir bayt kodu biçimi olmasına rağmen, ana makineye özel makine kodu oluşturmak için yine de bir derleyici aracılığıyla gönderilmesi gerekir. JavaScript gibi, derleyici de birden fazla aşamada çalışır. Basitçe söylenir: İlk aşama derlemede çok daha hızlıdır ancak genellikle daha yavaş kod oluşturur. Modül çalışmaya başladığında, tarayıcı hangi parçaların sık kullanıldığını gözlemler ve bunları daha optimize edilmiş ancak daha yavaş bir derleyici üzerinden gönderir.

Kullanım alanımızda ilginç bir nokta da, bir resmi döndürme kodunun bir kez, hatta iki kez kullanılmasıdır. Bu nedenle, çoğu durumda optimizasyon derleyicisinin avantajlarından hiçbir zaman yararlanamayız. Karşılaştırma yaparken bunu aklınızda etmek ö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ılar elde etmek için modülü bir kez çalıştırmalı ve o tek çalıştırmadan elde edilen sayılara göre 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ı veri üzerindeki farklı görünümlerdir. İlk grafikte tarayıcı başına, ikinci grafikte ise kullanılan dillere göre karşılaştırma yapıyoruz. Logaritmik zaman ölçeği seçtiğimi unutmayın. Aynı makine üzerinde çalıştırılamayan bir tarayıcı hariç, tüm karşılaştırmaların aynı 16 megapiksel test resmini ve aynı ana makineyi kullanması da önemlidir.

Bu grafikleri çok fazla analiz etmediğimizde, baştaki performans sorunumuzu çözdüğümüz ortadadır: Tüm WebAssembly modülleri yaklaşık 500 ms veya daha kısa sürede çalışır. Bu, başlangıçta ortaya koyduklarımızı onaylar: WebAssembly size öngörülebilir performans sunar. Hangi dili seçersek seçelim, tarayıcılar ve diller arasındaki fark minimum düzeydedir. Daha kesin belirtmek gerekirse, JavaScript'in tüm tarayıcılardaki standart sapması yaklaşık 400 ms. Öte yandan, tüm WebAssembly modüllerimizin tüm tarayıcılardaki standart sapması yaklaşık 80 ms'dir.

Yapılması gerekenler

Diğer bir metrik de WebAssembly modülümüzü oluşturmak ve squoosh'a entegre etmek için gösterdiğimiz çabanın miktarı. Bu çabaya sayısal bir değer atamak zordur, bu yüzden herhangi bir grafik oluşturmeyeceğim, ancak özellikle vurgulamak istediğim birkaç nokta var:

AssemblyScript sorunsuzdu. Yalnızca TypeScript'i WebAssembly yazmak için kullanmanıza izin vermekle kalmaz, kod incelemesini iş arkadaşlarım için çok kolay hale getirir. Aynı zamanda, performansı iyi olan çok küçük, yapıştırıcısız WebAssembly modülleri üretir. TypeScript ekosistemindeki "daha sevimli" ve "tslint" gibi araçlar muhtemelen işe yarayacaktır.

Rust, wasm-pack ile birlikte son derece uygundur ancak daha büyük WebAssembly projelerinde daha başarılıdır. Bağlamalar ve bellek yönetimi gerekir. 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, tutkal koduna atlayıp bunu da sadeleştirecek cesaret olmadan toplam boyutu (WebAssembly modülü + tutkal kodu) çok büyük hale getirdi.

Sonuç

Peki, bir JS sıcak yolunuz varsa ve bu işlemi WebAssembly ile daha hızlı veya daha tutarlı hale getirmek istiyorsanız hangi dili kullanmalısınız? Performans sorularında her zaman olduğu gibi cevap, bu soruya göre değişir. Peki, neler gönderdik?

Karşılaştırma grafiği

Kullandığımız farklı dillerin modül boyutu / performans dengesi açısından karşılaştırıldığında, en iyi seçim C veya AssemblyScript olabilir. Rust'ı göndermeye karar verdik. Bu kararın alınması için birkaç neden vardır: Şu ana kadar Squoosh'ta gönderilen tüm codec'ler Emscripten kullanılarak derlenmiştir. WebAssembly ekosistemine dair bilgimizi genişletmek ve üretimde farklı bir dil kullanmak istedik. AssemblyScript güçlü bir alternatiftir ancak proje nispeten yenidir ve derleyici Rust derleyicisi kadar olgun değildir.

Dağılım grafiğinde Rust ile diğer diller arasındaki dosya boyutu farkı çok büyük görünse de, gerçekte o kadar da önemli değildir: 2G üzerinde bile 500 B veya 1,6 KB yüklemek saniyenin 1/10'undan daha az sürer. Rust'un kısa süre içinde modül boyutu açısından boşluğu kapatacağını umuyorum.

Çalışma zamanı performansı açısından ise Rust'un tarayıcılar genelinde AssemblyScript'ten daha hızlı bir ortalaması vardır. Özellikle daha büyük projelerde, Rust'ın manuel kod optimizasyonlarına gerek kalmadan daha hızlı kod üretme olasılığı daha yüksektir. Ama bu, sizi en rahat kullandığınız uygulamayı kullanmaktan alıkoymamalıdır.

Söyleyeceklerim, AssemblyScript için çok iyi bir keşif oldu. Web geliştiricilerinin yeni bir dil öğrenmek zorunda kalmadan WebAssembly modülleri üretmelerine imkan tanır. AssemblyScript ekibi son derece duyarlı davrandı ve araç zincirilerini iyileştirmek için aktif olarak çalışıyor. Gelecekte AssemblyScript'i mutlaka takip edeceğiz.

Güncelleme: Pas

Bu makaleyi yayınladıktan sonra Rust ekibinden Nick Fitzgerald, bizi dosya boyutunu optimize etmeyle ilgili bir bölüm içeren mükemmel Rust Wasm kitabına yönlendirdi. Buradaki talimatları izlemek (en önemlisi, bağlantı süresi optimizasyonlarını ve manuel panik işlemeyi etkinleştirdi), "normal" Rust kodu yazmamızı ve dosya boyutunu büyütmeden Cargo (Rust'ın npm) kullanmaya geri dönmemizi sağladı. Rust modülü, gzip'ten sonra 370B'yle bitiyor. Ayrıntılar için lütfen Squoosh'ta açtığım halkla ilişkiler belgesine göz atın.

Bu yolculuktaki yardımları için Ashley Williams, Steve Klabnik, Nick Fitzgerald ve Max Graey'e özel teşekkürlerimizi sunarız.