Pengantar pertama untuk AssemblyScript

Dukungan untuk teknologi WebAssembly (Wasm) telah muncul di browser relatif baru-baru ini. Tetapi teknologi ini juga dapat memperluas kemampuan web, menjadikannya sebuah platform yang mampu mendukung aplikasi seperti itu yang biasanya dianggap sebagai desktop.

Menguasai WebAssembly bisa menjadi tugas yang menakutkan bagi pengembang web. Namun, kompiler AssemblyScript dapat memperbaiki situasi.


Penulis artikel, yang kami terbitkan hari ini, menawarkan pertama untuk berbicara tentang mengapa WebAssembly adalah teknologi yang sangat menjanjikan, dan kemudian untuk melihat bagaimana AssemblyScript dapat membantu membuka potensi Wasm.

Perakitan web


WebAssembly dapat disebut bahasa tingkat rendah untuk browser. Ini memberi pengembang kemampuan untuk membuat kode yang mengkompilasi menjadi sesuatu selain JavaScript. Ini memungkinkan program yang dimasukkan dalam halaman web berfungsi hampir secepat aplikasi asli untuk berbagai platform. Program semacam itu dijalankan dalam lingkungan yang terbatas dan aman.

Perwakilan tim yang bertanggung jawab untuk pengembangan semua browser terkemuka (Chrome, Firefox, Safari dan Edge) terlibat dalam pembuatan standar WebAssembly. Mereka menyetujui arsitektur sistem pada awal 2017. Sekarang semua browser di atas mendukung WebAssembly. Bahkan, teknologi ini dapat digunakan di sekitar 87% browser.

Kode WebAssembly ada dalam format biner. Ini berarti bahwa kode tersebut lebih kecil dari kode JavaScript yang sama dan memuat lebih cepat. Kode Wasm, selain itu, dapat disajikan dalam format teks , sehingga orang dapat membaca dan mengeditnya.

Ketika standar WebAssembly pertama kali muncul, beberapa pengembang berpikir bahwa itu bisa menggantikan JavaScript dan menjadi bahasa utama web. Tapi WebAssembly paling baik dilihat sebagai alat baru yang terintegrasi dengan baik dengan platform web yang ada. Ini adalah salah satu tujuan prioritasnya .

Alih-alih mengganti JavaScript di mana bahasa ini telah digunakan untuk waktu yang lama dan berhasil, WebAssembly memberikan peluang menarik baru bagi pengembang web. Benar, kode Wasm tidak memiliki akses langsung ke DOM, sehingga sebagian besar proyek web yang ada akan terus menggunakan JavaScript. Bahasa ini, selama bertahun-tahun pengembangan dan optimalisasi, sudah cukup cepat. Dan WebAssembly memiliki aplikasi sendiri:

  • Game
  • Perhitungan ilmiah, visualisasi, simulasi.
  • Aplikasi CAD.
  • Mengedit gambar dan video.

Semua penggunaan ini untuk Wasm dipersatukan oleh apa yang masing-masing aplikasi mereka biasanya dianggap sebagai desktop. Tetapi karena kenyataan bahwa WebAssembly memungkinkan Anda untuk mencapai tingkat kinerja yang mendekati asli, banyak aplikasi serupa sekarang dapat diimplementasikan menggunakan platform web.

WebAssembly dapat memanfaatkan proyek web yang ada. Contohnya adalah proyek Figma . Berkat penggunaan Wasm, waktu pemuatan proyek ini meningkat secara signifikan. Jika situs web menggunakan kode yang melakukan perhitungan berat, maka, untuk meningkatkan kinerja situs web ini, masuk akal untuk mengganti hanya kode tersebut dengan analog WebAssembly.

Anda mungkin ingin mencoba menggunakan WebAssembly di proyek Anda sendiri. Bahasa ini dapat dipelajari dan ditulis langsung di situ . Namun, bagaimanapun, WebAssembly awalnya dikembangkan sebagai target kompilasi untuk bahasa lain. Itu dirancang dengan dukungan yang baik untuk C dan C ++. Dukungan eksperimental Wasm muncul di Go 1.11. Banyak upaya yang dilakukan untuk menulis aplikasi Wasm di Rust .

Tetapi sangat mungkin bahwa pengembang web tidak ingin mempelajari C, C ++, Go, atau Rust hanya untuk menggunakan WebAssembly. Apa yang mereka lakukan Jawaban untuk pertanyaan ini dapat memberikan AssemblyScript.

AssemblyScript


AssemblyScript adalah kompiler yang mengubah kode TypeScript ke kode WebAssembly. TypeScript adalah bahasa yang dikembangkan oleh Microsoft. Ini adalah superset dari JavaScript, menampilkan dukungan tipe yang ditingkatkan dan beberapa fitur lainnya. TypeScript telah menjadi bahasa yang cukup populer . Perlu dicatat bahwa AssemblyScript mampu mengkonversi ke Wasm hanya set konstruksi TypeScript yang terbatas. Ini berarti bahwa bahkan seseorang yang tidak terbiasa dengan TypeScript dapat dengan cepat mempelajari bahasa ini pada tingkat yang cukup untuk menulis kode yang dipahami oleh AssemblyScript.

Selain itu, mengingat fakta bahwa TypeScript sangat mirip dengan JavaScript, kita dapat mengatakan bahwa teknologi AssemblyScript memungkinkan pengembang web untuk dengan mudah mengintegrasikan modul Wasm ke dalam proyek mereka tanpa perlu mempelajari bahasa yang sama sekali baru.

Contoh


Mari kita menulis modul AssemblyScript pertama kami. Semua kode yang akan kita diskusikan sekarang dapat ditemukan di GitHub . Untuk mendukung WebAssembly, kita memerlukan setidaknya Node.js 8.

Buat direktori baru, inisialisasi proyek npm dan instal AssemblyScript:

mkdir assemblyscript-demo cd assemblyscript-demo npm init npm install --save-dev github:AssemblyScript/assemblyscript 

Perhatikan bahwa AssemblyScript harus diinstal langsung dari repositori GitHub proyek. AssemblyScript belum diterbitkan dalam npm, karena pengembang belum menganggapnya siap untuk digunakan secara luas.

Kami akan membuat file tambahan menggunakan perintah asinit termasuk dalam AssemblyScript:

 npx asinit . 

Sekarang bagian scripts package.json kami harus mengambil bentuk berikut:

 {  "scripts": {    "asbuild:untouched": "asc assembly/index.ts -b build/untouched.wasm -t build/untouched.wat --sourceMap --validate --debug",    "asbuild:optimized": "asc assembly/index.ts -b build/optimized.wasm -t build/optimized.wat --sourceMap --validate --optimize",    "asbuild": "npm run asbuild:untouched && npm run asbuild:optimized"  } } 

File index.js terletak di folder root proyek akan terlihat seperti ini:

 const fs = require("fs"); const compiled = new WebAssembly.Module(fs.readFileSync(__dirname + "/build/optimized.wasm")); const imports = {  env: {    abort(_msg, _file, line, column) {       console.error("abort called at index.ts:" + line + ":" + column);    }  } }; Object.defineProperty(module, "exports", {  get: () => new WebAssembly.Instance(compiled, imports).exports }); 

Ini memungkinkan Anda untuk memasukkan modul WebAssembly dalam kode Anda menggunakan perintah need. Yaitu - dengan cara yang sama seperti modul JavaScript biasa terhubung.

Folder assembly berisi file index.ts . Ini memiliki kode sumber yang ditulis sesuai dengan aturan AssemblyScript. Kode boilerplate yang dihasilkan secara otomatis adalah fungsi sederhana untuk menambahkan dua angka:

 export function add(a: i32, b: i32): i32 {  return a + b; } 

Mungkin Anda mengharapkan tanda tangan dari fungsi yang mirip terlihat seperti add(a: number, b: number): number . Jadi akan terlihat jika ditulis dalam TypeScript biasa. Namun di sini, alih-alih tipe number , tipe i32 . Ini terjadi karena kode AssemblyScript menggunakan tipe WebAssembly spesifik untuk bilangan bulat dan angka floating point, daripada tipe angka generik dari TypeScript.

Mari kita kumpulkan proyek:

 npm run asbuild 

File-file berikut ini akan muncul di folder build :

 optimized.wasm optimized.wasm.map optimized.wat untouched.wasm untouched.wasm.map untouched.wat 

Ada versi perakitan yang dioptimalkan dan teratur. Setiap versi majelis memberi kita file biner .wasm, peta peta .wasm.map, dan representasi tekstual dari kode biner dalam file .wat. Presentasi pengujian kode Wasm dimaksudkan untuk programmer, tetapi kami bahkan tidak akan melihat file ini. Sebenarnya, salah satu alasan untuk menggunakan AssemblyScript adalah karena menghilangkan kebutuhan untuk bekerja dengan kode Wasm.

Sekarang mari kita jalankan Node.js dalam mode REPL dan pastikan bahwa modul Wasm yang dikompilasi dapat digunakan dengan cara yang sama seperti modul JS biasa:

 $ node Welcome to Node.js v12.10.0. Type ".help" for more information. > const add = require('./index').add; undefined > add(3, 5) 8 

Secara umum, ini semua yang diperlukan untuk menggunakan teknologi WebAssembly di Node.js.

Melengkapi proyek dengan naskah pengamat


Untuk membangun kembali modul secara otomatis selama pengembangan ketika membuat perubahan, saya sarankan menggunakan paket onchange . Faktanya adalah bahwa AssemblyScript belum memiliki sistem sendiri untuk memonitor perubahan file. Instal paket onchange:

 npm install --save-dev onchange 

Tambahkan asbuild:watch script ke package.json . Bendera -i disertakan dalam perintah sehingga proses pembangunan dimulai satu kali ketika skrip dipanggil, sebelum semua peristiwa terjadi.

 {  "scripts": {    "asbuild:untouched": "asc assembly/index.ts -b build/untouched.wasm -t build/untouched.wat --sourceMap --validate --debug",    "asbuild:optimized": "asc assembly/index.ts -b build/optimized.wasm -t build/optimized.wat --sourceMap --validate --optimize",    "asbuild": "npm run asbuild:untouched && npm run asbuild:optimized",    "asbuild:watch": "onchange -i 'assembly/**/*' -- npm run asbuild"  } } 

Sekarang, alih-alih terus menjalankan perintah asbuild , jalankan saja asbuild:watch sekali.

Performa


Kami akan menulis tes sederhana yang akan mengevaluasi tingkat kinerja kode Wasm. Ruang lingkup utama WebAssembly adalah untuk menyelesaikan tugas-tugas yang menggunakan prosesor secara intensif. Sebagai contoh, ini adalah semacam perhitungan "berat". Mari kita membuat fungsi yang mencari tahu apakah angka tertentu adalah prima.

Implementasi JS dasar dari fungsi serupa ditunjukkan di bawah ini. Ini diatur dengan sangat sederhana, memeriksa angka dengan kekerasan, tetapi untuk tujuan kami ini cocok, karena melakukan perhitungan dalam jumlah besar.

 function isPrime(x) {    if (x < 2) {        return false;    }    for (let i = 2; i < x; i++) {        if (x % i === 0) {            return false;        }    }    return true; } 

Fungsi serupa, ditulis untuk kompiler AssemblyScript, terlihat hampir sama. Perbedaan utama adalah adanya anotasi jenis dalam kode:

 function isPrime(x: u32): bool {    if (x < 2) {        return false;    }    for (let i: u32 = 2; i < x; i++) {        if (x % i === 0) {            return false;        }    }    return true; } 

Untuk menganalisis kinerja kode, kami akan menggunakan paket Benchmark.js . Pasang itu:

 npm install --save-dev benchmark 

Buat file benchmark.js :

 const Benchmark = require('benchmark'); const assemblyScriptIsPrime = require('./index').isPrime; function isPrime(x) {    for (let i = 2; i < x; i++) {        if (x % i === 0) {            return false;        }    }    return true; } const suite = new Benchmark.Suite; const startNumber = 2; const stopNumber = 10000; suite.add('AssemblyScript isPrime', function () {    for (let i = startNumber; i < stopNumber; i++) {        assemblyScriptIsPrime(i);    } }).add('JavaScript isPrime', function () {    for (let i = startNumber; i < stopNumber; i++) {        isPrime(i);    } }).on('cycle', function (event) {    console.log(String(event.target)); }).on('complete', function () {    const fastest = this.filter('fastest');    const slowest = this.filter('slowest');    const difference = (fastest.map('hz') - slowest.map('hz')) / slowest.map('hz') * 100;    console.log(`${fastest.map('name')} is ~${difference.toFixed(1)}% faster.`); }).run(); 

Inilah yang saya berhasil dapatkan setelah menjalankan perintah node benchmark di komputer saya:

 AssemblyScript isPrime x 74.00 ops/sec ±0.43% (76 runs sampled) JavaScript isPrime x 61.56 ops/sec ±0.30% (64 runs sampled) AssemblyScript isPrime is ~20.2% faster. 

Seperti yang Anda lihat, implementasi AssemblyScript dari algoritma itu 20% lebih cepat daripada implementasi JS. Namun, perhatikan bahwa tes ini adalah microbenchmark . Jangan terlalu mengandalkan hasilnya.

Untuk menemukan hasil yang lebih dapat diandalkan dari penelitian kinerja proyek-proyek AssemblyScript - Saya sarankan melihat ini dan tolok ukur ini .

Menggunakan Modul Wasm di Halaman Web


Mari kita gunakan modul Wasm kami di halaman web. Kami mulai dengan membuat file index.html dengan konten berikut:

 <!DOCTYPE html> <html>    <head>        <meta charset="utf-8" />        <title>AssemblyScript isPrime demo</title>    </head>    <body>        <form id="prime-checker">            <label for="number">Enter a number to check if it is prime:</label>            <input name="number" type="number" />            <button type="submit">Submit</button>        </form>        <p id="result"></p>        <script src="demo.js"></script>    </body> </html> 

Sekarang buat file demo.js yang kodenya ditunjukkan di bawah ini. Ada banyak cara untuk memuat modul WebAssembly. Yang paling efisien adalah mengkompilasi dan menginisialisasi mereka dalam mode streaming menggunakan fungsi WebAssembly.instantiateStreaming . Harap perhatikan bahwa kami perlu mendefinisikan kembali fungsi batal , yang dipanggil jika beberapa pernyataan tidak dieksekusi.

 (async () => {    const importObject = {        env: {            abort(_msg, _file, line, column) {                console.error("abort called at index.ts:" + line + ":" + column);            }        }    };    const module = await WebAssembly.instantiateStreaming(        fetch("build/optimized.wasm"),        importObject    );    const isPrime = module.instance.exports.isPrime;    const result = document.querySelector("#result");    document.querySelector("#prime-checker").addEventListener("submit", event => {        event.preventDefault();        result.innerText = "";        const number = event.target.elements.number.value;        result.innerText = `${number} is ${isPrime(number) ? '' : 'not '}prime.`;    }); })(); 

Selanjutnya, instal paket server statis . Kita memerlukan server karena fakta bahwa untuk menggunakan fungsi WebAssembly.instantiateStreaming , modul harus diservis menggunakan application/wasm MIME application/wasm .

 npm install --save-dev static-server 

Tambahkan skrip yang sesuai ke package.json :

 {  "scripts": {    "serve-demo": "static-server"  } } 

Sekarang npm run serve-demo dan buka URL host lokal di browser. Jika Anda memasukkan nomor tertentu dalam formulir, Anda dapat mengetahui apakah itu sederhana atau tidak. Sekarang, dalam mengembangkan AssemblyScript, kita telah jauh dari menulis kode untuk menggunakannya di Node.js dan di halaman web.

Ringkasan


WebAssembly, dan karenanya AssemblyScript, tidak dapat entah bagaimana mempercepat situs apa pun secara ajaib. Tapi Wasm tidak pernah ditugaskan untuk mempercepat segalanya. Teknologi ini luar biasa karena membuka jalan ke web untuk aplikasi jenis baru.

Hal serupa dapat dikatakan tentang AssemblyScript. Teknologi ini menyederhanakan akses ke WebAssembly untuk sejumlah besar pengembang. Hal ini memungkinkan, ketika membuat kode dalam bahasa yang dekat dengan JavaScript, untuk menggunakan kemampuan WebAssembly untuk memecahkan masalah komputasi yang kompleks.

Pembaca yang budiman! Bagaimana Anda menilai prospek untuk menggunakan AssemblyScript di proyek Anda?


Source: https://habr.com/ru/post/id477272/


All Articles