Quando ho un po' di tempo cerco sempre di informarmi e di studiare. Ed i blog dei colossi informatici sono uno delle mie fonti.
Qualche giorno fa mi ha colpito questo titolo sui
blog di MSDN:
Introduction to the HTML5 Web Workers: the JavaScript multithreading approach.
Javascript? Multithreading? Personalmente ho sempre pensato a queste due parole separate, mai nella stessa frase.
Faccio una piccola digressione per i meno tecnici. Il
JavaScript è un linguaggio di programmazione che viene utilizzato generalmente nelle pagine web per modificare l'aspetto delle pagine a seguito dell'interazione dell'utente (ad esempio pensate al menù a tendina che si trova in alto nella navigazione di queste pagine).
Il JavaScript è un linguaggio semplice, poco rigoroso, con alcune caratteristiche della programmazione orientata agli oggetti ed adottato da molti
Web Designers, per dare interattività alle pagine web.
Ogni pagina web è statica, l'html permette di realizzare una impaginazione dei contenuti, ma nulla di più. Tramite il javascript è possibile cambiare l'aspetto della pagina dopo che è stata caricata, e modificarla a seconda dell'interazione con l'utente. Ad esempio su questo sito, potete vedere nella navigazione in alto dei menù a scomparsa (ad esempio provate a posizionare il menù su chi siamo). Questo effetto è possibile tramite il javascript che interagendo con il mouse dell'utente permette di far apparire i box che contengono il menù a scomparsa.
Il javascript ha fra le sue caratteristiche di essere interpretato, che vuol dire che non è scritto in linguaggio macchina (i famosi 0 e 1 che può leggere un processore), ma è scritto in un codice intellegibile dal programmatore e quindi necessita di essere convertito in linguaggio macchina per poter essere processato dalla cpu. Questa conversione può essere fatto a priori (e quindi si parla di linguaggio compilato) oppure durante l'esecuzione (come nel JavaScript, e prende il nome di interpretato).
Un linguaggio interpretato converte, al volo, ogni singola istruzione ogni volta che la deve eseguire, quindi questo significa che se la deve eseguire 10 volte, questa verrà convertita 10 volte, con un ovvio degrado delle prestazioni.
Generalmente il linguaggi interpretati sono più semplici e meno prestazionali.
Una caratteristica che ha sempre contraddistinto in Javascript fino a questo momento è di essere single-thread.
Facciamo un piccola seconda digressione
su cosa è un Thread. I computer moderni hanno la capaci di eseguire più programmi contemporaneamente, malgrado ci sia un unico processore. Questo possibilità che abbiamo è dovuta al fatto che i moderni sistemi operativi suddividono l'uso del processore fra i vari programmi attivi, quindi n millisecondi al browser, n al media player, n al programma di posta e così via. Essendo questi passaggi di esecuzione da un programma all'altro molto veloci, generalmente a l'utente sembra che queste cose avvengano contemporaneamente. A meno di non lanciare troppi programmi insieme e quindi il processore si satura e tutti i programmi si bloccano, perchè non ci sono abbastanza risorse di calcolo per soddisfare tutte le richieste.
Ogni programma è un processo in esecuzione nel processore.
Ogni singolo processo può essere spezzato in sotto-processi indipendenti. Che funzionano allo stesso modo come i processi del sistema operativo. Questi sotto processi prendono il nome di thread. A differenza dei processi però, non è il sistema operativo ad occuparsi di lanciarli e di gestirli, è il programmatore il gestore. Il quale si occupa di spezzettare il suo programma in in parti indipendenti e si occupa poi di sincronizzarli e di permettere loro di scambiare dati.
Questo impone un modello di programmazione asincrona, che è un po' più complicata, ma
permette di aumentare le prestazioni dei programmi. L'aumento di prestazioni è spiegabile molto velocemente. Generalmente le applicazioni sono single-thread. Immaginate che il vostro programma sia un piccolo bot, che naviga su web alla ricerca di informazioni. Se questo deve scaricare una pagina da un sito, prima di poter iniziare l'analisi della stessa dovrà attendere che sia finito lo scaricamento. Durante lo scaricamento, anche l'interfaccia del programma risulta bloccata, perché il thread che si occupa dell'interazione con l'interfaccia è lo stesso che si occupa dell'elaborazione, e quindi essendo in uso, tutta la finestra risulta come congelata.
Se per caso il sito dal quale stiamo scaricando è molto lento, la sua lentezza si scaricherà sulla nostra applicazione. Nel caso di programmazione Multi Threading invece, possiamo far girare lo scaricamento delle pagine in un thread distinto da quello dell'interfaccia, la quale quindi non rimarrà bloccata, anzi tutti i pulsanti rimarranno funzionanti, ad esempio il classico STOP, per fermare il programma. Ma possiamo fare di più, possiamo aprire ad esempio 10 thread ed in ognuno mettere in scaricamento una pagina. In questo modo, anche se qualche sito è lento, diversi thread continueranno a scaricare sfruttando al massimo la banda del collegamento ad internet. Ed eventualmente potremmo avere un thread che si occupa di elaborare le pagine scaricate ed inserire i dati all'interno di un database. Questo scenario evidentemente ci da una notevole accelerazione delle prestazioni.
Il multi threading aumenta la velocità di molti programmi
I vantaggi però non sono solo nell'accesso di risorse internet, ma in effetti nell'accesso di qualsiasi risorsa, memoria e disco ad esempio. Ed inoltre i moderni processori hanno più core, il che significa che è come se fossero più processori che lavorano in parallelo. Spezzando l'esecuzione in più thread si fa in modo che l'elaborazione non vada su un solo core, ma che possa essere divisa fra i core disponibili. Un programma single thread con una elaborazione impegnativa, ad esempio un rendering video, gira su un solo core. Se noi adottassimo una programmazione Multi Threading ed abbiamo un moderno processore, ad esempio a 4 core, potremmo spezzare l'elaborazione in n thread, in numero maggiore dei core disponibili, in modo che ognuno di essi possa andare in esecuzione su un core distinto, e quindi potremmo sfruttare al 100% le capacità elaborativa della CPU.
I core di un moderno computer (ognuno può eseguire una attività in autonomia)
Quello che vedete qui sopra è il task manager di un moderno computer (il mio per la precisione,
da bravo geek posso non sfoggiare la potenza del mio portatile?:-) ), dove vediamo 8 CPU. Nel caso in questione il processore è un
i7 di seconda generazione con 4 core e tecnologia
HyperThreading che fa in modo di far credere al sistema operativo che ci siano il doppio dei core. È una tecnologia che in pratica implementa un threading hardware per sfruttare al meglio i core. Non è come avere il doppio dei core, però permette un incremento di prestazioni.
In un processore come questo il Multi Threading è essenziale per sfruttare la potenza di calcolo al 100%.
Il JavaScript è sempre stato single-thread. Ed
è sempre stato eseguito nello stesso thread che il browser usa per renderizzare la pagina. Per questo motivo i Javascript troppo impegnativi vengono bloccati, perchè porterebbero al blocca del browser. Ed è sempre per lo stesso motivo, che i web designers, per fare delle animazioni devono usare il setTimeout, per spezzettare l'esecuzione dell'animazioni in frazioni eseguite ad intervalli regolari, per evitare che durante la loro esecuzione monolitica, l'utente non si trovi l'interfaccia bloccata, tanto da non poter nemmeno cliccare sui link.
A questo punto, torniamo al tema del post. Aver letto
Introduction to the HTML5 Web Workers: the JavaScript multithreading approach. Mi ha colpito molto.
Il MultiThreading è sempre stato connotazione di linguaggi più blasonati. A memoria non ricordo alcun linguaggio di scripting che io abbia usato con tale caratteristica. Da qui il mio stupore.
Non voglio andare nel dettaglio del linguaggio, per questo rimando all'articolo originale, quello che mi interessa ora è parlare delle possibilità e delle caratteristiche.
Il MultiThreading in Javascript arriva grazie all'HTML 5 ed ai Web Workers che permettono di spostare l'esecuzione al di fuori del thread della user interface, ovvero quello che si occupa del rendering della pagina a partire dall'HTML.
Essendo una novità che arriva dall'HTML 5 ovviamente non è supportata da tutti i brower.
Per adesso la troviamo in
- Internet Explorer 10 PP2 (Platform Preview)
- Firefox (dal 3.6)
- Safari (dal 4.0)
- Chrome
- Opera 11
Per adesso non sono supportati da alcun browser mobile.
Altra cosa molto interessante. Da un web worker, non è possibile fare tutto. Ovvero non si ha un completo accesso a tutte le caratteristiche del JavaScript. Vediamolo in dettaglio.
I diritti di accesso degli HTML 5 Web Workers
La notate la grossa differenza dall'immagine?
Non è possibile accedere al DOM. Immagino lo sconcerto di alcuni.
Ma se non posso accedere al DOM, a che mi serve? Se non posso modificare la pagina, a che mi serve spostare l'elaborazione su un Web Worker?
Semplice. Si lavora come in altri linguaggi, si fa fare l'elaborazione al Web Worker e si passano i risultati al thread principale che si occupa di aggiornare la pagina. In questo scenario, questa nuova funzionalità può essere di grande aiuto nei seguenti casi:
- elaborazione di immagini;
- gestione di una grande quantità di dati (immaginate i 100 mila punti di interesse da caricare su una mappa);
- analisi di testi (correzione ortografica su grandi testi, ricerca in in grossi dizionari);
- elaborazione di video.
L'unico limite è l'immaginazione.
Nell'articolo sono presenti anche un paio di esempio.
Fontana in HTML 5
Una fontana in HTML 5. Demo molto interessante. La fontana è costituita da centinaia di punti che si muovono indipendentemente. Sicuramente molto impegnativo a livello elaborativo. Però funziona bene senza bloccare l'interfaccia del browser. Da questo noto però anche un'altra cosa. Ho provato la demo su Chrome che ha uno dei migliori motori javascript. La demo gira, però impegna al 60% il mio processore che è un i7 ed impegna tutti i core. Se pensiamo ad i videogiochi che riescono a muovere milioni di triangoli al secondo, le prestazioni del javascript rimangono decisamente basse. Con queste nuove caratteristiche, occorre uno sforzo in più per i produttori di browser per rendere più prestante il javascript.
Ray Tracing in HTML 5
Ray Tracing in HTML 5. Questa demo mi ha colpito molto, il
Ray Tracing in javascript è una cosa molto ambiziosa. Provatela mettendo come Pixel Size, Best quality (1x1) e provatela sia su Internet Explorer (da 9 in giù) e su Chrome. Il primo non suppora i Web Workers e quindi impiega molti secondi per arrivare al risultato, durante i quali tutta l'interfaccia è bloccata. Il secondo invece potendo sfruttare tutti i core del processore è enormemente più veloce.
Da sviluppatore mi entusiasma l'idea di poter usare i thread anche in javascript, c'è da dire che per diffondersi occorrerà che aumenti lo studio nello sviluppatore web medio.
Una tale caratteristica è consona di linguaggi più blasonati e la programmazione concorrente non è certo nelle corde di un programmatore javascript. Può essere però una bella sfida per aumentare la professionalità del settore.