Codice efficiente per le Windows Store Apps by Matteo Anelli

14
© Copyright NTT DATA Italia – All Rights Reserved This document contains confidential Company information. Do not disclose it to third parties without permission from the Company. 22/03/2013 Ottimizzare le Windows Store Apps

Transcript of Codice efficiente per le Windows Store Apps by Matteo Anelli

© Copyright NTT DATA Italia – All Rights Reserved This document contains confidential Company information. Do not disclose it to third parties without permission from the Company.

22/03/2013

Ottimizzare le Windows Store Apps

© Copyright NTT DATA Italia – All Rights Reserved 2

M052 - 03

Chi Sono?

Matteo AnelliIngegnere InformaticoClasse 1978

Senior Project Manager di NTT DATA

Microsoft Competence Center Progetti Internazionali Ricerca Applicata Innovazione

Qualcuno di voi mi avrà ascoltato su ArsLudicast

Twitter: matteoanelliFacebook: ziggybeePSN/XBL: Ziggybee

© Copyright NTT DATA Italia – All Rights Reserved 3

M052 - 03

Vari tipi di performance

Start-Up PerformanceImportante per le App one-shot che non hanno bisogno di essere usate per più di qualche minuto alla volta, come feed reader, applicazioni meteo o in generale di consultazione. Gli utenti vogliono arrivare alle informazioni nel minor tempo possibile!

Execution PerformanceImportante per le App che fanno un uso intensivo di calcoli e multimedia. Per questo tipo di software la user experience e la fluidità d’uso sono l’aspetto più importante. Importanti per Giochi, Media Apps e applicazioni Data Intensive.

Battery PerformanceImportantissimo per applicazioni always on o che comunque vanno utilizzate per lunghi periodi. Importante per applicazioni che utilizzano l’esecuzione in background, Giochi e Media Apps.

Buone performance di esecuzione spesso non sono una garanzia di una buona durata della batteria e viceversa

© Copyright NTT DATA Italia – All Rights Reserved 4

M052 - 03

Start-Up: Packaging e Caching

Può essere banale ma un grande discriminante per le perfomance di un’applicazione Javascript è l’accesso alle risorse che la compongono (JS, CSS, HTML, Immagini, etc). Un buon metodo per ottimizzare i tempi di risposta è condensare le informazioni all’interno dei package.

Le dimensioni e la frammentazione del packaging di un’App influenzano anche i tempi di ripristino dal background ed il memory footprint

Bytecode CachingQuando il JS è eseguito, Windows 8 salva una copia del bytecode generato in una sua cache interna. In questo modo il secondo avvio sarà molto più efficiente: il codice è già pre-compilato!

Attenzione! Per avvalersi di questa funzionalità i file JS devono essere: Codificati in UTF8, con Byte Order Mark Linkati staticamente nella root della pagina HTML di start.

Occhio quando usate tool di authoring HTML esterni a Visual Studio…

JS

© Copyright NTT DATA Italia – All Rights Reserved 5

M052 - 03

Start-Up: Caricamento degli Script

Link statico

Ottime prestazioni di caricamento del singolo script (usa Bytecode Cache!) Se gli script sono tanti (o grandi) lo start-up ne risenteCaricamento Dinamico

Può caricare il codice on Demand.Deferred Loading

In questo modo l’applicazione completa l’attivazione prima di iniziare a caricare gli script, ottimizzando i tempi.

var s = document.createElement('script'); s.src = 'code.js'; document.head.appendChild(s);

<script type="text/javascript" src='code.js'></script>

<script type="text/javascript" src='file1.js' defer='defer'></script>

JS

© Copyright NTT DATA Italia – All Rights Reserved 6

M052 - 03

Start-Up: Una migliore inizializzazione

(function () {"use strict";var app = WinJS.Application;function initialize() {

//inizializzazione globale: setup della UI, dati, etc...}function activatedHandler(e) {

if (e.detail.kind == Windows.ApplicationModel.Activation.ActivationKind.launch) { if (app.sessionState) { // ripristino della sessione

} WinJS.UI.processAll();

}if (e.detail.kind ===

Windows.ApplicationModel.Activation.ActivationKind.filePicker) { // Process the file picker request.

}}

document.addEventListener("DOMContentLoaded", initialize, false);app.addEventListener("activated", activatedHandler, false); app.start();

})();

L’inizializzazione global conDOMContentLoad è più efficiente,e rende l’evento activated più snello,limitando il tempo di ripristino e le allocazioni inutili. JS

© Copyright NTT DATA Italia – All Rights Reserved 7

M052 - 03

Execution: Fragment Cache

Un buon metodo per rendere le applicazioni molto fluide è quello di trarre vantaggio dalla Fragment Cache delle Windows Store Apps.

Applicazioni molto piccole che svolgono gran parte delle loro operazioni durante il caricamento (es.: meteo, feed reader, etc…) possono trarre molto giovamento da una costruzione manuale di tutti i Fragment legati al dato, così da rendere la navigazione tra viste e drill-down istantanei

Costruire un fragment costa tempo di elaborazione e tenerlo in cache costa memoria.

L’applicazione di questa tecnica ha ottimi risultati se i fragment sono piccoli e gli update non sono troppo frequenti. Non c’è bisogno di gestire manualmente l’object pooling o il disposing dei fragment

Se il databind è statico o reagisce a precise azioni dell’utente renderCopy può letteralmente mettere le ali alla vostra App!

JS

WinJS.UI.Fragments.renderCopy("/pFragment.html", domObject).done(function(){

//init e processAll});

© Copyright NTT DATA Italia – All Rights Reserved 8

M052 - 03

Execution\Battery: Attenzione alle closure!

function Vector(x, y, z) { this.x = x; this.y = y; this.z = z; this.magnitude = function () {

return Math.sqrt((this.x * this.x) + (this.y * this.y) + (this.z * this.z));

}; this.normalize = function () {

var m = this.magnitude(); return new Vector(this.x / m, this.y / m, this.z / m);

} } In JS quando una classe o un metodo anonimo viene eseguito, viene creato un contesto di esecuzione per l’oggetto chiamante e instanziata una nuova closures.

Stress alla CPU Possibilità di Stack Overflow e chiusure improvvise Dispendio di RAM e quindi pessime prestazioni

JS

Ogni istanza alloca anche due closure ed i relativi contesti!

© Copyright NTT DATA Italia – All Rights Reserved 9

M052 - 03

Execution\Battery: PIMP my Javascript!

function Vector(x, y, z) { this.x = x; this.y = y; this.z = z;

} Vector.prototype = { magnitude: function () {

return Math.sqrt((this.x * this.x) + (this.y * this.y) + (this.z * this.z)); }, normalize: function () {

var m = this.magnitude(); return new Vector(this.x / m, this.y / m, this.z / m);

} } //oppureObject.defineProperty(Vector.prototype, "magnitude", { get: function () {

return Math.sqrt((this.x * this.x) + (this.y * this.y) + (this.z * this.z)); }

});

Properties to Instances, Methods to Prototypes

JS

Non si alloca una closure per ogni istanza…

Metodo incapsulato in una property read only

© Copyright NTT DATA Italia – All Rights Reserved 10

M052 - 03

XAML: brutto ma efficiente

UI complesse possono trarre grande vantaggio da un design in XAML: l’esecuzione degli effetti grafici è più veloce e le API consentono un controllo migliore e più razionale di effetti, tipografia e resa a schermo.

Nonostante sembri un mark-up, scrivere XAML è equivalente a scrivere codice C#Un po’ di consigli per sopravvivere al cambio di paradigma: Ottimizzare i Resource Dictionary. I template di default prevedono un Dictionary a livello di App,

Appaiare i Dictionary ai componenti che fanno uso delle proprietà può distribuire il carico di memoria e di caricamento di un’applicazione sino a livelli sorprendenti.

Riutilizzare i Brush e gli stili, evitando di definirli come proprietà inline (migliore gestione della Fragment Cache e della memoria). Metteteli nei Dizionari!

Fare caching bitmap dei controlli. quasi tutti i componenti di UI in XAML non sono altro che il risultato di grafica vettoriale. Nel caso di interfacce o componenti complessi che non subiscono trasformazioni o animazioni continue può essere molto utile abilitare il caching bitmap.

Mantenere il mark-up e le gerarchie il più snelle possibili. Ogni tag istanzia un’oggetto e databinder, DependanceProperies e altri costrutti dinamici possono stressare molto l’App e dovrebbero essere usati solo dove strettamente necessario.

C#

© Copyright NTT DATA Italia – All Rights Reserved 11

M052 - 03

Execution\Battery: Gestione degli eventi efficiente

In C#, evitare di sovraccaricare gli Event Handler! Essi vengono eseguiti nello stesso thread del flusso degli eventi dell’App, quindi se un event Handler ha tempi di esecuzione elevati, rischia di rendere l’App poco fluida o bloccarla completamente.Utilizzare async/await per evitare di bloccare il flusso di esecuzione dell’app.

public class TurnProcessor { // ... private async void EndTurn_Click(object sender, RoutedEventArgs e) { await Task.Run(() => ProcessNextTurn()); // Aggiorna la UI }

private async Task ProcessNextTurn() { // Calcola il nuovo Turno… } // ... }

C#

Mandare in stallo la CPU può voler dire bloccarla con il 100% del carico per alcuni secondi. Quando questo accade gli effetti sulla durata della batteria sono devastanti e si possono lasciare all’utente dei feedback spiacevoli, come un terminale che scotta…

© Copyright NTT DATA Italia – All Rights Reserved 12

M052 - 03

Execution: attenzione alle interop calls!

Le API di sistema sono incapsulate in API .NET.

Ogni volta che un’API di sistema viene eseguita, la Virtual Machine effettua un passaggio di contesto al codice nativo. Questa transizione può essere molto costosa in termini di performance ed è opportuno rimuoverle o limitarle.

Attenzione ai namespace usati!

Windows: API native che utilizzano Interop System: si tratta di API Managed che non

incorrono in tale limitazione di performance.

Fare molta attenzione alle Collection!

System.Collection ha delle performance migliori degli oggetti in Windows.Foundation.Collection.

C#

© Copyright NTT DATA Italia – All Rights Reserved 13

M052 - 03

TIPS: Consigli utili…

Consumi non lineari! un chip che lavora al 20% non è equivalente a 5 chip che lavorano al 100%. In generale l’utilizzo continuo peggiora di molto (e in maniera non lineare) i consumi!

Non stressare la comunicazione dati! per quanto detto sopra, è meglio comunicare ad intermittenza che in lunghi burst di dati. Evitate «l’effetto Facebook» al ripristino della vostra applicazione che si connette ad Internet!

Testa tra le nuvole! Azure è semplice da usare, economico e molto flessibile. Se avete bisogno di preprocessare dei dati, un piccolo proxy Azure può rendere la vostra App più scattante ed efficiente rispetto all’esecuzione locale.

Ricordatevi di testate le App con la batteria quasi scarica! In questa situazione le CPU ARM funzionano a regime ridotto e possono avere prestazioni molto più basse della media del dispositivo.

Ricordatevi di Windows RT! Windows RT può avere performance anche 4 volte peggiori rispetto ad un desktop della generazione corrente. Se mirate ai Desktop o a Surface Pro ricordatevi che la vostra App verrà installata anche su questi dispositivi…

I dinosauri non passano mai di moda! Per molti anni il grosso del parco macchine di Windows 8 saranno i vecchi notebook e i vecchi desktop. Con un disco meccanico. Devo aggiungere altro?

© Copyright NTT DATA Italia – All Rights Reserved 14

M052 - 03

Grazie!