WebAssembly: apa dan bagaimana


Artikel ini didasarkan pada presentasi saya di konferensi ITSubbotnik, yang diadakan pada 2 November 2019 di Moskow.


Secara umum, saya adalah programmer backend, tetapi saya tertarik dengan teknologi ini, memungkinkan saya untuk menggunakan pengetahuan backend saya di depan.


Masalah


Mari kita mulai dengan masalah yang sedang dipecahkan oleh teknologi (relatif baru) ini. Masalah ini adalah dengan cepat mengeksekusi kode di browser . Cepat - ini berarti "lebih cepat daripada JavaScript", idealnya secepat yang dimungkinkan oleh prosesor kami saat ini.
Selain itu, secara historis, persyaratan tambahan penting secara bertahap muncul di sekitar masalah ini:


  • Nol konfigurasi - itu harus menjadi solusi "di luar kotak", tidak lain adalah browser.
  • Aman - teknologi baru seharusnya tidak menciptakan ancaman baru, kami sudah ada hubungannya dengan keamanan.
  • Cross-platform - browser dijalankan pada semua prosesor utama, termasuk platform mobile.
  • Nyaman bagi pengembang - yaitu bagi kami.

Sejarah sebelum Wasm


Kami melihat banyak opsi untuk mengeksekusi kode di browser. Kita dapat mengatakan bahwa ada pemenang dan pecundang di bidang ini.



Pemenang: Ini jelas JavaScript; mesin V8 yang membuat JS sangat cepat; serta HTML5.


Pecundang: ActiveX - jika Anda ingat, teknologi ini memungkinkan Anda untuk melakukan apa saja dengan mesin secara umum, mis. keamanan sangat buruk; Flash - sekarang kita menyaksikan era penurunan Flash, meskipun ActionScript bekerja di dalamnya, pada kenyataannya, JavaScript yang sama; Silverlight - dia pasti muncul terlambat untuk menempati ceruk yang serius.
Akibatnya, semua plugin hilang, termasuk karena masalah keamanan.


Ada upaya lain untuk menyelesaikan masalah, sudah ada di browser:


  • NaCl - Klien Asli yang diusulkan oleh Google; kode asli langsung di browser, yang tentu saja mogok untuk lintas platform; Mozilla tidak mendukung inisiatif ini, akibatnya, implementasinya hanya di Chrome.
  • PNaCl - Portable Native Client - subset LLVM IR digunakan sebagai kode portabel; juga tidak didukung di Mozilla, sekali lagi hanya Chrome. Akibatnya, Google menolak untuk mendukung PNaCl pada Mei 2017.

asm.js


asm.js adalah inisiatif lain yang menarik, sudah dari Mozilla Foundation, yang membawa kita lebih dekat ke topik WebAssembly. Itu muncul pada 2010, dan pada 2013 menjadi tersedia untuk umum.


asm.js adalah himpunan bagian dari JavaScript, Anda dapat mengkompilasi kode dari C dan C ++ menggunakan kompiler Emscripten.


Karena ini juga JavaScript, kode ini akan dieksekusi di browser apa pun. Selain itu, browser modern utama telah lama dapat dengan cepat mengenali asm.js dan mengkompilasinya secara efisien ke dalam kode asli prosesor. Dibandingkan dengan kode asli yang diperoleh langsung dari C / C ++, kode yang diperoleh dari asm.js lebih lambat hanya 1,5-2 kali (50-67%).



Di sebelah kiri adalah kode fungsi paling sederhana di C / C ++, di sebelah kanan ditunjukkan apa yang berubah setelah dikompilasi menjadi asm.js. Pertama, kita melihat baris 'use asm' , ini adalah marker, yang membuatnya jelas bahwa kode untuk asm.js selanjutnya. Dan dalam kode ini kita melihat konstruksi bentuk |0 , ini adalah operasi bitwise ATAU dengan nilai nol. Menurut spesifikasi, hasil operasi ini adalah integer bertanda 32-bit. Tetapi jenis ini bahkan tidak ada dalam JavaScript. Namun, tipe ini muncul sebagai hasil dari operasi ini, mis. itu pada dasarnya adalah pemeran untuk jenis tertentu.


Secara umum, asm.js adalah penggunaan pengetahuan kami tentang bagaimana mesin browser mengkompilasi JS untuk mengoptimalkan pekerjaan ini.


Apa itu WebAssembly?



WebAssembly (atau Wasm ) adalah format biner yang dijalankan di browser, mesin virtual, dan hasil kompilasi dari bahasa tingkat tinggi.


Wasm bukan bahasa pemrograman, seperti Java bytecode bukan bahasa pemrograman, tetapi hasil kompilasi dan blok kode yang sedang berjalan.


Seseorang yang sangat pandai mengatakan bahwa nama web assembly (yaitu, "assembler untuk web") sama sekali tidak benar, karena itu bukan assembler (bukan bahasa pemrograman) dan itu tidak ada hubungannya dengan web (karena itu hanya mesin virtual).


Pembuat WebAssembly dipandu oleh tujuan dan batasan berikut - lihat video Evolving Wasm menjadi istilah yang salah: Andreas Rossberg .



Bahkan, mereka turun ke tiga hal - cross-platform, ringkas, kecepatan. Tetapi ada persyaratan penting lainnya, itu adalah “kemampuan menjual” - para pengembang browser utama harus mengambil dan mengambil inisiatif. Akibatnya, dimungkinkan untuk "menjual", perwakilan Google, Mozilla, Microsoft dan Apple mengambil bagian dalam pengembangan spesifikasi.


Mari kita lihat apa itu Wasm seperti mesin virtual.



Ini adalah "prosesor fiksi", tetapi tanpa register, semuanya dilakukan melalui stack. Hanya empat tipe data: dua bilangan bulat, dua mengambang. Seperangkat operasi yang relatif sederhana - lihat spesifikasi dan tabel interaktif .



Model memori datar: satu blok dialokasikan untuk memori, yang ukurannya merupakan kelipatan 64 KB. Berikut adalah kode, data, konstanta, variabel global, tumpukan tumbuh, tumpukan tumbuh. Anda dapat membuat tumpukan secara otomatis tumbuh jika perlu, sementara blok memori bertambah dengan kelipatan 64 KB.


Pointer tidak digunakan (ini dilakukan untuk keamanan), sebagai gantinya indeks digunakan. Indeks ini 32-bit, sehingga menangani memori hingga 4 GB.


Semua memori WebAssembly sepenuhnya dapat diakses dari JavaScript, baik untuk membaca dan menulis.



Mari kita lihat model runtime WebAssembly. Wasm selalu dimuat dan HANYA dipanggil dari JavaScript. Selain itu, JS dan Wasm bekerja di kotak pasir yang sama, dan dieksekusi oleh mesin yang sama.


Perhatikan bahwa Anda juga dapat memanggil JS dari Wasm. Ini bisa berupa pemanggilan fungsi dengan melewati argumen dan mengembalikan nilai, atau bisa juga mengeksekusi string arbitrer sebagai kode-JS.


Mencoba WebAssembly


Untuk memulai dengan WebAssembly, saya sarankan menggunakan situs WasmFiddle atau WebAssembly Studio - ini adalah cara sederhana dan visual untuk memahami sendiri apa sebenarnya Wasm itu.



Di sini, kode sumber dalam C / C ++ ada di kiri atas (dalam hal ini, fungsi rekursif untuk menghitung angka Fibonacci), di kanan atas adalah kode JS untuk memuat Wasm, instantiating modul Wasm dan memanggil fungsi fib() darinya. Ketika kita menekan tombol Build, kita mendapatkan blok kode Wasm (file .wasm), yang kita selalu dapat memperluas ke representasi tekstual (file .wat).


Representasi tekstual ini dengan sekelompok kurung pada dasarnya adalah pohon sintaksis abstrak (AST). Ya, sebenarnya dengan tanda kurung, itu menyerupai bahasa Lisp. Secara teori, kita dapat mengedit kode sebagai representasi teks, dan kemudian menciutkannya kembali ke dalam format biner - ini mengingatkan pada pemrograman bahasa assembly. Tapi biasanya kami mendapatkan Wasm biner sebagai hasil kompilasi dari bahasa tingkat tinggi.


2017: Produksi Siap


Pada November 2017, WebAssembly dinyatakan "siap digunakan dalam produksi." Spesifikasi untuk semua bagian utama Wasm telah disiapkan, implementasi Wasm dirilis di semua browser utama. Jadi, untuk WebAssembly, MVP dirilis - Minimum Viable Product, versi 1.0, yang sedang kita hadapi sekarang.


Dukungan Browser


Pada akhir 2017, rilis semua browser utama dengan dukungan WebAssembly dirilis:



Pengecualian adalah IE11, tidak ada dukungan untuk itu, dan kemungkinan besar itu akan hilang. Diasumsikan bahwa untuk browser lama akan ada polyfill - kemampuan untuk mengubah Wasm menjadi asm.js; ada prototipe seperti itu, tetapi sejauh yang saya lihat, proyek-proyek ini ditinggalkan, tampaknya, masyarakat tidak sanggup melakukannya.


Sekarang di antara semua browser yang diinstal, ~ 88% mendukung Wasm .



Dukungan bahasa


Agar bahasa favorit Anda dikompilasi dalam Wasm, Anda memerlukan kompiler untuk memberikan tujuan kompilasi ini. Sekarang beberapa bahasa mendukung Wasm, dan ada lebih banyak dan lebih banyak lagi setiap bulan. Lihat appcypher / awesome-wasm-langs .


  • C / C ++ - melalui Emscripten , dukungan yang sangat bagus.
  • Dukungan Rust - Wasm muncul sejak lama, ekosistem di sekitar Wasm dibangun sebagian besar berdasarkan Rust.
  • Java - melalui TeaVM, JWebAssembly, Bytecoder - pada level eksperimental.
  • Kotlin - ada dukungan di Kotlin / Asli melalui backend LLVM - eksperimental.
  • Pergi
  • C # - melalui Blazor (mono) dan di masa depan di Uno Platform .
  • TypeScript - melalui AssemblyScript .

Belum lama ini ada berita bahwa LLVM sekarang mendukung Wasm sebagai target kompilasi. Hal ini memudahkan pengembang bahasa pemrograman untuk mendapatkan lebih banyak bahasa yang dikompilasi dalam Wasm.


Gunakan kasing


Ini mungkin salah satu pertanyaan utama - "Bagaimana saya bisa menggunakan Wasm?"


WebAssembly sudah aktif menggunakan:


  • Game, mesin game, mesin fisika, VR / AR - misalnya, Godot , Doom 3
  • Emulator, mesin virtual - misalnya, DOSBox
  • Editor Grafik / 3D - Figma , AutoCAD
  • Klien web untuk platform perdagangan finansial - Saya melihat presentasi tentang dua klien tersebut
  • Codec dan filter audio / video - mis. Ffmpeg
  • Basis data - mis. Sqlite

Skenario lain yang mungkin:


  • Aplikasi web progresif (PWA)
  • Pengakuan oleh jaringan saraf yang terlatih

Performa


Kinerja Wasm adalah salah satu faktor penjualan utama, tetapi apa yang sebenarnya terjadi?


Dibandingkan dengan JavaScript, ternyata rata-rata Wasm lebih cepat, tetapi dalam setiap kasus tertentu Anda perlu melakukan perbandingan JS / Wasm, karena dapat berubah menjadi berkali-kali lebih baik dan beberapa kali lebih buruk. Mungkin juga sangat tergantung pada browser yang digunakan.


Bahkan, kinerja puncak JS dan Wasm adalah sama, karena keduanya akhirnya berubah menjadi kode prosesor asli. Tetapi JS jauh lebih mudah hilang dalam kinerja, dan Wasm memberikan pendekatan yang lebih "merata".


Sebagai aturan, Wasm berkinerja baik dalam komputasi volumetrik. Di mana ada banyak operasi memori, Wasm kehilangan. Nah, masalah utama dalam aplikasi nyata adalah lambatnya JS <-> Wasm interop. Lihat misalnya patokan .



Pada Juli 2019, artikel ilmiah "Tidak Begitu Cepat: Menganalisa Kinerja WebAssembly vs Kode Asli . " Para penulis menerapkan kemampuan untuk menjalankan utilitas konsol Linux di bawah WebAssembly untuk menjalankan benchmark, dan menggunakan benchmark SPEC untuk mengevaluasi kinerja Wasm dibandingkan dengan tes yang sama pada asm.js dan kode asli.


Hasilnya adalah sebagai berikut:


  • Wasm 30% lebih cepat dari JavaScript (rata-rata untuk tes ini)
  • Wasm 50% lebih lambat dari kode asli (rata-rata dalam tes ini)

Para penulis artikel juga memberikan analisis tentang alasan Wasm “melambat”:


  • sekitar dua kali lebih banyak operasi pemuatan / penyimpanan data dibandingkan dengan kode asli;
  • lebih banyak cabang - disebabkan oleh kebutuhan untuk pemeriksaan tambahan saat mengakses memori;
  • lebih banyak melewatkan cache L1.

Secara umum, sebenarnya, kinerja tidak begitu buruk. Selain itu, analisis ini akan memungkinkan pengembang peramban untuk membuat Wasm lebih cepat.


Di masa depan, Wem akan mempercepat tidak hanya karena optimasi yang lebih baik di browser, tetapi juga karena fitur baru, seperti: memblokir operasi pada memori, dukungan untuk instruksi SIMD, dukungan untuk utas.


Apa yang akan terjadi selanjutnya?


Bagaimana WebAssembly berkembang?


Pertama, tim spesifikasi untuk Wasm melanjutkan pekerjaannya. Spesifikasi ada pada tahap (fase) yang berbeda, ada "peta jalan" tertentu untuk pekerjaan ini.


Secara khusus, dalam waktu dekat kami berharap dapat melihat fitur-fitur tersebut lebih lanjut:


  • Konversi float-to-int non-trapping - sekarang konversi dari nilai mengambang ke integer dalam beberapa kondisi dapat menyebabkan pengecualian; Untuk seorang programmer, ini sangat tidak terduga, jadi semua konversi seperti itu harus dibungkus, kehilangan kinerja. Fitur ini menyelesaikan masalah.
  • Multi-nilai - kemampuan untuk mengembalikan lebih dari satu nilai dari suatu fungsi, kemampuan untuk membuat instruksi baru yang mengembalikan lebih dari satu nilai - misalnya, hasil pembagian dan sisa pembagian, atau hasil penambahan dan carry bit.
  • Jenis Referensi adalah pengenalan jenis anyref, yang berarti "tautan ke sesuatu di tumpukan JS", langkah pertama untuk mempercepat interaksi dengan JS.

Kedua, pengembang peramban, untuk bagian mereka, mengimplementasikan spesifikasi ini, yaitu secara bertahap fitur baru ditambahkan ke Wasm, pertama-tama disembunyikan "di bawah bendera" dalam pengaturan, dan kemudian dihidupkan secara default.


Misalnya, berikut adalah daftar fitur Chrome yang terkait dengan WebAssembly .
Untuk Firefox, daftar serupa dapat ditemukan di sini .


WebAnsembly di luar browser


Seperti disebutkan di atas, Wasm pada dasarnya tidak terhubung ke web, itu hanya mesin virtual. Ini berarti bahwa itu juga dapat digunakan di luar web.


Sekarang ada beberapa skenario untuk menggunakan Wasm di luar browser:


  • Node.js - Node.js didasarkan pada mesin V8 yang mendukung Wasm.
  • Aplikasi konsol terpisah, kode aplikasi dijalankan dalam Wasm VM - contoh runtime seperti: wasmtime , wasmer.
  • Wasm VM digunakan sebagai perpustakaan dari bahasa lain - misalnya, wasmer memungkinkan Anda menyebut dirinya dari selusin bahasa yang berbeda.

Untuk Wasm yang bekerja di luar browser, pembatasan kotak pasir tidak lagi diperlukan, sebaliknya, akses ke fungsi sistem diperlukan - sistem file dan file, konsol I / O, dll. Ini menyebabkan terciptanya WebAssembly System Interface (WASI), spesifikasi API lintas-platform yang mirip dengan POSIX. Lihat WebAssembly / WASI dan wasi.dev .



Langkah selanjutnya adalah membuat manajer paket - Wasm Package Manager (WAPM) - wapm.io. Di sini Anda dapat mengambil file .wasm selesai dan menggunakannya dalam aplikasi Anda. Biasanya, kita berbicara tentang versi Wasm dari beberapa perpustakaan terkenal. Beberapa paket ditandai dengan tag WASI, yang berarti bahwa mereka hanya dapat digunakan dalam skenario di luar browser.


Kesimpulan


Jadi, WebAssembly sangat memungkinkan untuk digunakan, sudah "siap produksi" selama dua tahun sekarang.
Menggunakan Wasm mungkin memberikan beberapa peningkatan kecepatan dibandingkan dengan kode JavaScript serupa, tetapi Anda harus selalu memeriksa untuk melihat apakah Anda mendapatkan peningkatan kecepatan.
Dukungan Wasm dari bahasa pemrograman terus berkembang.


Yah dan yang paling penting, WebAssembly agak "mengubah lanskap" dari web - memberi kami skenario penggunaan baru yang dapat kami terapkan dalam aplikasi kami.


Referensi



Daftar yang luar biasa:



Video:


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


All Articles