
guide
Tutti i linguaggi per diventare uno sviluppatore di app per Android.
Le applicazioni Web basate su JavaScript sono vere e proprie applicazioni moderne, interattive e multimediali (come i giochi e le […]
Le applicazioni Web basate su JavaScript sono vere e proprie applicazioni moderne, interattive e multimediali (come i giochi e le applicazioni HTML5 create per il desktop), con richieste hardware talvolta anche elevate.
Questo fenomeno ha scatenato una nuova engine war, con tutti i maggiori produttori di browser impegnati a scontrarsi aspramente nel tentativo di creare e dotare il proprio software dell’ambiente che fornisce – da tutti i punti di vista – la migliore esperienza utente in assoluto nell’esecuzione del codice JavaScript.
L’esperienza utente che delle applicazioni JavaScript non è determinata esclusivamente dalle caratteristiche del motore che le esegue: è molto importante il codice JavaScript che scriviamo e le pratiche messe in campo (e da evitare) per renderlo maggiormente “digeribile” dal browser.
In altre parole, una buona applicazione è risultato anche di una stesura del codice attenta all’ottimizzazione. I compilatori JIT faranno solo la loro parte, trasformando il codice in sequenze eseguibili dalla macchina.
Per eseguire test di massima delle performance di un engine JavaScript, i produttori si affidano principalmente a una serie di benchmark: determinare la bontà generale del motore non è un compito facile, così i benchmark costituiscono almeno uno strumento capace di fornire dati misurabili dai quali partire per ottimizzare ulteriormente il prodotto.
Per eseguire in proprio un test delle capacità del motore del proprio browser è possibile, ad esempio, utilizzare il Bubblemark animation test di Alexey Gavrilov, disponibile anche per altre tecnologie generalmente impiegate nei browser (come Silverlight/WPF, Flash, Adobe AIR e Java).
È altrettanto importante testare il proprio codice, o meglio i componenti di cui è composto, creando ad esempio degli Unit Test con uno dei tanti framework disponibili, come Jasmine (derivato da JSUnit), oppure appoggiandosi a siti che consentono di eseguire i test direttamente online e condividerne i risultati, come nel caso di JSPerf.
Quando occorre manipolare le proprietà di un oggetto tramite JavaScript, occorre evitare la ripetizione inutile di accesso alle funzionalità del DOM, ad esempio la ricerca di un elemento in base al suo nome tramite getElementById():
document.body.box.getElementById('item1').style.left = coords.x + "px";
document.body.box.getElementById('item1').style.top = coords.y + "px";
Lo stesso vale per l’accesso agli oggetti che costituiscono le proprietà dell’elemento ottenuto dal DOM (come nel caso di style nell’esempio sopra). La situazione ovviamente peggiora se l’accesso al DOM avviene attraverso librerie e framework, come JQuery, tramite l’uso di espressioni e filtri.
Il codice dell’esempio potrebbe essere ottimizzato in questo modo:
var itemStyle = document.body.box.getElementById('item1').style;
itemStyle.left = coords.x + "px";
itemStyle.top = coords.y + "px";
È molto importante ricordare che le applicazioni girano anche su dispositivi mobili, per questo diventa importante ottimizzare cicli di calcolo e di conseguenza l’uso della batteria, come stiamo per vedere.
È importante evitare di fare lavoro inutile, cioè di impegnare la CPU più del necessario quando non occorre, riducendo la fluidità dell’applicazione.
Un caso tipico è quello che si verifica quando si vogliono animare elementi nella pagina; molti si appoggiano all’uso delle funzioni setInterval()
o setTimeout()
per invocare periodicamente la funzione di aggiornamento grafico, specificando il minor tempo possibile per l’intervallo tra una chiamata e l’altra, cioè 0
(zero):
setInterval(myDrawRoutine, 0);
Questo metodo consuma molta CPU (e pertanto più batteria, risorsa critica su dispositivi mobili e tablet) e lascia meno spazio all’elaborazione dei calcoli tradizionali rallentando le operazioni in background. Al suo posto occorre utilizzare la funzione requestAnimationFrame(), che consente di sincronizzare le operazioni di disegno con la frequenza corretta di refresh dello schermo.
requestAnimationFrame prende come parametro la funzione di callback da richiamare ad ogni frame e ritorna un codice requestID
.
Per evitare problemi di compatibilità è possibile sfruttare un semplice polyfill che faccia come suggerito qui:
(function() {
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame;
})();
Anche se troviamo qualcosa di più robusto su questo articolo di Paul Irish
Già che ci siamo riportiamo anche un esempio:
function step(time) {
console.log(time);
if (time < 150) {
requestAnimationFrame(step);
}
}
requestAnimationFrame(step);
Come si capisce facilmente mandando in esecuzione lo snippet, il parametro time
della callback viene utilizzato come contatore del tempo passato dalla prima richiesta. Ecco il tracciato della console:
In questa pagina è possibile vedere un esempio significativo di questo problema e l’efficacia della soluzione proposta.
Occorre prestare particolare attenzione al tipo di dato a cui appartengono le proprietà e gli argomenti delle funzioni JavaScript, evitando la conversione automatica operata da JavaScript quando tali valori vengono assegnati a variabili o parametri di tipo diverso, soprattutto se tale operazione viene ripetuta più volte, periodicamente o all’interno di un ciclo.
In questi casi, è bene costruirsi una cache del valore convertendolo tramite le funzioni incorporate in JavaScript (come parseInt() e toString()) e memorizzandolo in una variabile di appoggio e usando poi tale variabile al posto dell’originale.
Il linguaggio JavaScript supporta molti “automatismi” che conferiscono flessibilità nella scrittura del codice: è possibile aggiungere dinamicamente proprietà a un oggetto, moltiplicare tra loro numeri e stringhe, convertire automaticamente tipi di dati; tuttavia è necessario tenere ben presente che queste operazioni, sebbene semplifichino il codice scritto in termini di forma e quantità, possono avere un impatto sulle performance dell’applicazione.
La risposta a questo problema non è ovviamente quella di abbandonare completamente queste feature, magari finendo con il complicare a tal punto il codice del programma da renderlo illeggibile e andando alla ricerca spasmodica della forma più ottimizzata possibile sacrificandone la comprensibilità; documentazione alla mano, occorre approfondire come opera la funzione che si sta utilizzando in una determinata riga di codice e saper scegliere il modo più adatto di ottenere lo stesso risultato senza eccedere in sintesi e cripticità del codice, ma nemmeno abusando degli automatismi del linguaggio.
Vi sono alcune best practice da seguire per creare “oggetti veloci”. Una di queste riguarda l’accesso alle proprietà, evitando l’uso dell’operatore delete
per rimuovere interamente una proprietà da un oggetto, operazione particolarmente lenta in JavaScript. È preferibile invece adottare un valore di default e assegnarlo alla proprietà, scegliendo comunque di mantenerla piuttosto che rimuoverla.
Analogamente, è preferibile definire tutte le proprietà all’interno del costruttore, astenendosi dall’aggiungerne dinamicamente in un secondo momento, poiché l’engine ottimizza l’accesso alle prime dando per scontato che siano quelle più frequentemente utilizzate nel resto dell’applicazione.
Infine, è bene non abusare dei “getter” e dei “setter” poiché introdotti nelle versioni recenti dello standard del linguaggio e non ottimizzati da tutti i compilatori JavaScript.
Le operazioni matematiche in JavaScript possono risultare poco performanti quando si utilizzano variabili di tipo differente nel contesto di una espressione, poiché JavaScript tende a generare oggetti, allocati nella memoria heap, per conservare al loro interno i valori coinvolti nel calcolo dell’espressione. Il fenomeno è noto con il nome di boxing.
È meglio cercare innanzitutto di uniformare i tipi e sforzarsi quando possibile di eseguire operazioni tra valori numerici, meglio se interi, potendo così sfruttare l’ottimizzazione applicata dal compilatore JavaScript nel calcolo allocando tali valori nello stack. Ciò vale anche per i numeri decimali a virgola mobile (float), da utilizzare tuttavia solo quando servono dato che sono composti da 64 bit e pertanto sono più lenti rispetto agli interi.
È importante infine utilizzare in modo consistente variabili e parametri, facendo assegnazioni che non ne alterino il tipo originale di appartenenza.
Anche nell’uso degli array vi sono diverse ottimizzazioni applicabili: ad esempio, è meglio preallocare lo spazio necessario agli array per il numero di elementi che dovrà contenere, evitando di modificarne “al volo” le dimensioni in seguito, a meno che non sia necessario.
Per memorizzare valori numerici all’interno di vettori, è possibile ricorrere all’uso dei typed arrays: si tratta di implementazioni (purtroppo non disponibili in tutti i compilatori JavaScript) che consentono di dichiarare array del tipo numerico che si intende utilizzare; ad esempio, un Float64Array
definisce un vettore di valori float a 64 bit. Questo tipo di array gode di diverse ottimizzazioni, quali l’allocazione sullo stack piuttosto che nella memoria heap.
Se vuoi aggiornamenti su Ottimizzare JavaScript per mobile e browser apps inserisci la tua email nel box qui sotto:
Compilando il presente form acconsento a ricevere le informazioni relative ai servizi di cui alla presente pagina ai sensi dell'informativa sulla privacy.
La tua iscrizione è andata a buon fine. Se vuoi ricevere informazioni personalizzate compila anche i seguenti campi opzionali:
Compilando il presente form acconsento a ricevere le informazioni relative ai servizi di cui alla presente pagina ai sensi dell'informativa sulla privacy.
Una chiacchierata con Matteo Collina sul protocollo MQTT e alcuni consigli su come svolgere il mestiere dello sviluppatore.
Tutti i linguaggi per diventare uno sviluppatore di app per Android.
Come creare applicazioni per il Web con PHP e MySQL per il DBMS.
Tutte le principali tecnologie per diventare uno sviluppatore mobile per iOS.
I fondamentali per lo sviluppo di applicazioni multi piattaforma con Java.
Diventare degli esperti in tema di sicurezza delle applicazioni Java.
Usare Raspberry Pi e Arduino per avvicinarsi al mondo dei Maker e dell’IoT.
Le principali guide di HTML.it per diventare un esperto dei database NoSQL.
Ecco come i professionisti creano applicazioni per il Cloud con PHP.
Lo sviluppo professionale di applicazioni in PHP alla portata di tutti.
Come sviluppare applicazioni Web dinamiche con PHP e JavaScript.
Fare gli e-commerce developer con Magento, Prestashop e WooCommerce.
Realizzare applicazioni per il Web utilizzando i framework PHP.
Creare applicazioni PHP e gestire l’ambiente di sviluppo come un pro.
Percorso base per avvicinarsi al web design con un occhio al mobile.
Realizzare siti Web e Web application con WordPress a livello professionale.
Come creare database e collection, inserire, estrarre, aggiornare e rimuovere dati da una base di dati MongoDB con Python
Impariamo ad utilizzare Takamaka, una blockchain Java Full Stack, per scrivere codice Java installabile ed eseguibile su una blockchain
StandardJS è uno strumento in ambiente Node.js, per la definizione ed il controllo di uno standard di codifica in JavaScript.
Android è il sistema operativo mobile più diffuso attualmente sul mercato. Imparare a sviluppare app per Android è quindi la chiave d’accesso ad uno dei mercati più attivi nello sviluppo mobile. Questa guida completa e dettagliata fornisce tutte le informazioni necessarie per imparare a progettare ed implementare app moderne e funzionali per Android.