WebAssembly, meglio conosciuto come Wasm, è certamente uno degli argomenti cool di noi dev ultimamante. Ma esattamente, di cosa si tratta?
La prima definizione, e forse la più semplice, arriva direttamente dal consorzio W3C, ossia possiamo pensare a WebAssembly come un formato bytecode standardizzato per l’esecuzione di programmi. Magari indaghiamo un pò più a fondo.
Ci sono programmi che vengono eseguiti soltanto con l’ausilio, o l’assistenza, di un Sistema Operativo. Possiamo citare C, C++, Go, Rust, e altri che probabilmente nemmeno conosco; tutti questi linguaggi, una volta compilati, generano un file binario eseguibile direttamente sul Sistema Operativo che li ospita.
Esistono altri tipi di programmi, scritti con linguaggi di scripting, il cui codice viene letto, interpretato ed eseguito in successione. Tutti noi abbiamo scritto qualche riga in Javascript, ma ci sono pure Python, PHP, Perl, Ruby e, anche in questo caso, altri che non conosco.
Infine, esistono programmi compilati in un formato intermedio, un bytecode, che per essere eseguiti richiedono la presenza di un strato speciale, un runtime, o una macchina virtuale. I più conosciuti, almeno per me, sono C#, che viene eseguito dal CRL (Common Language Runtime), così come tutti i linguaggi .NET, e Java, che richiede la presenza della JVM (Java Virtual Machine).
E WebAssembly? A quale famiglia appartiene? WebAssembly è un formato bytecode, come C# e Java, ma che può essere eseguito da qualsiasi runtime compatibile con WebAssembly. Apparentemente, dunque, nulla di nuovo all’orizzonte, ma sono alcune particolari caratteristiche a renderlo interessante. Vediamo quali, ma soprattutto vediamo di capire come si è evoluta la storia di WebAssembly.
WebAssembly e i Browser
Se è vero che WebAssembly è un formato bytecode che può essere eseguito da un qualsiasi runtime compatibile, allora bisogna capire dove risiedono questi runtime compatibili.
L’idea originale era proprio quella che tutti i principali browser web avessero questo runtime incorporato. Mentre scrivo questo mi ricordo di un talk, molti anni fa alla Web Conference in Bicocca, di Scott Hanselman, che diceva che il Javascript era destinato a diventare l’assembler del futuro. WebAssembly non è Javascript, ma come al solito, Hanselman non è caduto lontano dall’albero. Ma perchè nei browser? Un post di Luke Wagner, autore di WebAssembly, ci da una prima risposta
WebAssembly defines a portable, size and load-time-efficient format and execution model specifically designed to serve as a compilation target for the web.
Partendo da questo assunto la speranza era che tutti i compilatori dei più diffusi linguaggi di programmazione, C, C++, Go, Ruby, Rust avrebbero generato bytecode Wasm in grado di essere recuperato ed eseguito nel browser come un normale programma.
La prospettiva, se così la vogliamo chiamare, era che WebAssembly si sarebbe sbarazzato di Javascript e si sarebbe proposto come il futuro dei già blasonati, e superati, applet Java, Flash, Silverlight, etc., ma, inspiegabilmente, tutto questo non è successo, e col senno di poi, possiamo aggiungere, fortunatamente.
WebAssembly beyond the Browser
Quella che poteva essere interpretata come una sconfitta, in realtà, si è dimostrata la vera vittoria di WebAssembly. La ragione di questo la possiamo trovare nelle caratteristiche di questo formato dettate proprio dall’ambiente dei browser
- Strong Security: caratteristica dettata proprio dall’ambiente a cui è destinato. Non possiamo fidarci di chiunque voglia far girare un applicativo all’interno del nostro browser
- Small binary sizes: Il terzo punto delle Fallacies of Distributed Computing ci ricorda proprio che la banda non è infinita, quindi bisogna limitare le dimensioni dei file
- Fast loading and running: Ormai lo sanno anche i muri che le applicazioni web devono essere veloci e reattive. Gli utenti si annoiano velocemente se i tempi di risposta sono troppo lenti
- Support for many operating systems and architectures: il tempo di Windows con processore Intel, o macOS con M1 sono finiti. O meglio, ora gli utenti hanno a dispozione, oltre a questi, diversi altri tipi di dispositivi, ed un applicativo in grado di girare su tutti è fondamentale
- Interoperability with the browser: da soli si perde! Va bene che il formato WebAssembly è in grado di girare nel browser, ma per essere appetibile deve essere in grado di interagire con l’HTML, il CSS e ovviamente, con Javascript
Queste caratteristiche, fortemente incentrate sulla connettività, hanno reso WebAssembly sicuramente interessante per il browser, ma non solo.
WebAssembly e il Cloud
Molto tempo fa partecipai allo sviluppo del primo portale web per l’acquisto e la vendita di quote fondi in Italia per Clienti Istituzionali. In pratica un eCommerce per Banche e Istituti di Gestione Patrimoniale. Ricordo benissimo la sala server, ed il misticismo che girava attorno ad essa. Tutto, e ripeto tutto, era ridondato. Dai server alle linee telefoniche. Un tale investimento potevano permetterselo appunto Banche o istituzioni simili. Poi, un bel giorno, Amazon ha deciso di recuperare un pò di perdite offrendo al mondo la potenza di calcolo dei propri datacenter. Il Cloud, così come lo conosciamo, era nato!
Oggi ci sono diversi Cloud provider, e non è più necessario avere una batteria di server nel sottoscala per distribuire applicazioni in rete, i costi sono, più o meno (ma questo è discorso per un altro articolo) accessibili a tutti. Però attenzione, i costi non sono spariti, ed il guadagno dei grossi Cloud provider sta proprio nel ridurre il più possibile i costi di gestione delle loro enormi infrastrutture.
Quando distribuiamo i nostri applicativi tramite Cloud ci aspettiamo principalmente sicurezza e costi ridotti. Il primo aspetto dipende in gran parte dal fornitore, e dalle scelte che noi andiamo a fare nel momento della configurazione del servizio, il secondo invece è un pò un mix di responsabilità, ma in ogni caso in gran parte ricondicibili alla dimensioni dei file necessari al funzionamento del nostro applicativo. Lo abbiamo ricordato prima, la banda non è infinita, e soprattutto non è gratuita. Lato fornitore poi ci possiamo aggiungere il fatto che non è cosa semplice dover supportare soluzioni scritte per diversi sistemi operativi e con tecnologie diverse, una certa uniformità non farebbe certo male. Insomma, ci sono diversi aspetti da considerare, alcuni già visti, altri nuovi, che potremmo riassumere in questo elenco
- Strong Security
- Small binary sizes
- Fast loading and running
- Support for many OSes and Architectures
- Interoperability with Cloud Services
Ops … ma non le abbiamo già viste poco sopra?
Certamente, quando Amazon ha messo a disposizione i suoi datacenter, tutte queste caratteristiche non erano rispettate; in fondo ciò che aveva fatto era stato condividere delle macchine virtuali con il mondo, e forzatamente, dimensioni e caratteristiche di queste ultime dovevano essere ridotte.
Docker ha cambiato completamente le regole del gioco, insieme a Kubernetes ha reso scalabili le nostre soluzioni, e anche un pò più semplici da distribuire. Non parleremmo oggi di microservizi se non avessimo Docker a supportarci.
Pochi anni dopo Docker è apparso WebAssembly, forte delle caratteristiche viste sopra che, guarda caso, sono proprio quelle richieste dal Cloud. WebAssembly sembra proprio perfetto per creare soluzioni leggere, facilmente distribuibili, sicure e interconnesse da distribuire nel Cloud. Non sostituisce, almeno per ora, i container, così come i container non hanno sostituito le macchine virtuali, ma si presenta come soluzione alternativa e complementare.
WebAssembly e il resto dei linguaggi
Vediamo di entrare un pò nei dettagli tecnici di WebAssembly. Tanto per essere originali i primi linguaggi ad essere presi in considerazione e considerati “ideali per WebAssembly” sono stati i soliti ignoti, C e C++, che sono alla base di gran parte dell’informatica di oggi. Accanto a questi due candidati però si è fatto strada anche Rust, per lo più per il fatto che produce file eseguibili di ridotte dimensioni, veloci ed ha una gestione della memoria sicura. Bisogna ricordare che Mozilla, una delle grandi organizzazioni dietro al mondo WebAssembly, ha investito molto in Rust e l’unione dei due ecosistemi, Rust e WebAssembly, ne ha tratto giovamento. Ad oggi, Rust è probabilmente il miglior sistema host non browser per WebAssembly, ed anche il miglior linguaggio di compilazione con notevoli strumenti per gli sviluppatori.
In tempi più vicini ai nostri sono apparsi sulla scena altri linguaggi, inspirati più o meno a quelli nati per il mondo web. AssemblyScript, inspirato proprio a TypeScript, ma progettato proprio per la compilazione in WebAssembly. Per chi come me è più vicino al mondo .NET, con la versione 7.0, in arrivo questo autunno, dovrebbe trovare novità sulla compilazione delle applicazioni Blazor Wasm direttamente in WebAssembly, saltando l’interpretazione del CLR, ma anche Go, Swift e altri si stanno accodando a questo trend. Kotlin sta lavorando a questo supporto, Python e Ruby si sono uniti recentemente, e via via altri linguaggi sino ad arrivare a COBOL! Insomma, WebAssembly sta veramente catturando l’attenzione di tutti. Come nelle favole con il lieto fine, il linguaggio che forse meno ci si aspettava nell’ecosistema di WebAssembly si è dimostrato JavaScript. Proprio quello che, soprattutto all’inizio, in molti davano per quello che sarebbe poi stato sostituito da WebAssembly stesso. Il realtà al termine del 2021 il motore che alimenta Mozilla FireFox, JavaScript SpiderMonkey, ha rilasciato una versione con compilazione in WebAssembly, ed improvvisamente il linguaggio che doveva essere soppiantato si è trovato ad essere parte dello stesso eco-sistema.
Finita, per ora, la carrellata sui linguaggi che si stanno accodando a WebAssembly ci resta un’ultima nota prima di concludere. Vi stare chiedendo come sia possibile eseguire WebAssembly in così tanti dispositivi, Sistemi Operativi e ambienti, cloud incluso, diversi. Tutti questi sistemi hanno bisogno di un sistema per esporre le caratteristiche dell’host al modulo WebAssembly, e per capire di cosa si tratta dobbiamo presentare WASI (WebAssembly System Interface).
WASI (WebAssembly System Interface)
Molti progetti sono nati con grandi ambizioni, e poi sono finiti nel nulla. WASI è nato come progetto ambizioso, ma poi … è andato ben oltre le più rosee aspettative.
L’idea iniziale era quella di creare uno strato fra il file binario WebAssembly ed il Sistema Operativo, un host tecnicamente parlando, in grado di fornire tutto il necessario al programma Wasm per funzionare. Il programma viene scritto normalmente, con tutte le sue funzionalità rispetto al file system, alle connessioni di rete e alla lettura delle variabili d’ambiente, ma anzichè dialogare direttamente con il Sistema Operativo, tutte le chiamate vengono passate all’host che fa da garante. Ogni connessione di rete potrebbe essere bloccata se ritenuta pericolosa, perchè l’host, nel progetto iniziale, era libero di aggiungere i livelli di sicurezza più severi.
Già detto così il progetto appare ambizioso, ma ad un certo punto il piano iniziale è cambiato. I progettisti di WASI hanno pensato che una libreria standard non era esattamente quello che volevano. Allora hanno optato per una soluzione in cui un modulo WebAssembly ospite potesse richiedere un filesystem, o un database, o ancora, una connessione di rete e l’ambiente host potesse soddisfare tutte queste richieste, rispettando le regole di affidabilità, sicurezza e prestazioni che si erano posti all’inizio.
Ad oggi WASI è ancora in evoluzione, ma già si possono vedere i risultati; stanno nascendo famiglie di prodotti che sfruttano appieno queste peculiarità, la versione Wasm di Blazor in .NET 7.0 sembra propio essere uno di questi prodotti. Non importa quanto tempo ci vorrà per completare il progetto, perchè quello che conta è che stà accadendo ora.