Aber schnell!
Performanceaspekte in Cross-Plattform-HTML5-
Anwendungen
Gregor Biswanger | CEO von CleverSocial.de, Freier Dozent, Berater, Trainer und Autor
about.me/gregor.biswanger
Bitte warten… Sprecher wird geladen…
Über mich
 Gründer von CleverSocial.de
 Freier Dozent, Berater und Trainer
 Schwerpunkte .NET-Architektur, Agile Prozesse,
XAML, Web und Cloud
 Technologieberater für die Intel Developer Zone
 Sprecher auf Konferenzen und User Groups
 Freier Autor für heise.de, dotnetpro,
WindowsDeveloper und viele weitere Fachmagazine
 Video-Trainer bei video2brain und Microsoft
Gregor Biswanger
Microsoft MVP, Intel Black Belt &
Intel Software Innovator
dotnet-blog.net
about.me/gregor.biswanger
Unsere gemeinsame Reise
 Performance messen
 Welche Probleme gibt es bei Hybrid-Apps
 Wie funktioniert der Browser
 Zahlreiche Performance-Tipps für Web-Entwickler
HTML5 ist langsam?
Nein, das stimmt nicht!
Was genau bedeutet schnell?
100 ms ist ein gutes und realistisches Ziel
Das ist unser Ziel!
Was ist Apache Cordova?
Wie Hybrid-App Entwicklung mit HTML5?
Die Lösung: Hybrid-Apps mit Apache Cordova
 Cordova ist ein JavaScript-Framework für lokal installierbare WebApps
auf mobilen Endgeräten
 Ist Open-Source und liegt auf GitHub
 Unterstützte Plattformen: iOS, Android, LG webOS, Symbian OS,
BlackBerry, Tizen, Firefox OS, Windows Phone, Windows 8
 Features
 Zugriff auf Sensoren
 Plattformspezifische Funktionen (Notifications)
 Zugriff auf Kontakte
 Zugriff auf lokale Dateien
 Cordova bietet kein UI Framework!
cordova.apache.org
Der Cordova Build
Cloud Compiler
JS
CSS
HTML
oder
AppsWWW Projekt
Local Compiler
Plattform (Betriebssystem)
Native App (Android, WP, iOS)
WebView (Browser)
Hybrid-App Architektur
WWWProjekt
Frontend – HTML5 und CSS (Twitter Bootstrap)
Backend - JavaScript (Apache Cordova)
Plattform (Betriebssystem)
Native App (Android, WP, iOS)
WebView (Browser)
Cordova Plugin Architektur
Frontend – HTML5 und CSS (Twitter Bootstrap)
Backend - JavaScript (Apache Cordova)
API
Sensoren (Hardware)
Plugin
Plugin
Android und Windows Phone benötigen
Zugriffsberechtigungen und/oder
Hardware nicht vorhanden.
Wie können wir die Performance testen?
Wichtig! Am besten auf alten Geräten testen…
Dann bringt ein Test auf neuer Hardware…
Okay, also eine Web-Browser-App im Vollbildmodus…
Problem!
!=
Das Crosswalk Project
 Open-Source (BSD Lizenz)
 Embedded Chrome Chromium
 Für Android und Tizen
 Ab Android Version 4
 Ab Tizen Version 3
 Nachteil: Paketgröße circa 15-20 MB
 An Crosswalk Lite wird aktuell gearbeitet
 Paketgröße circa 7 MB crosswalk-project.org
Kostenlos Builden via Intel XDK
xdk.intel.com
WKWebView
 Cordova Plug-In
 Ersetzt die Standard
UIWebView
 Ab iOS 8 verfügbar
Einbinden ganz einfach via Cordova Plug-In
 Über die Plugin ID:
 com.telerik.plugins.wkwebview
Beim Intel XDK ganz einfach über den Plug-In Manager
Dann müssen wir analysieren, wie ein Browser unter
der Haube arbeitet…
Erst wird alles geladen…
BÖSE!
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="css/bootstrap.css">
<script src="js/jquery.js"></script>
<script src="js/bootstrap.js"></script>
</head>
<body>
...
</body>
</html>
Gut… 
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="css/bootstrap.css">
</head>
<body>
...
<script src="js/jquery.js"></script>
<script src="js/bootstrap.js"></script>
</body>
</html>
Get auch für HTML5 Browser mit async-Tag…
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="css/bootstrap.css">
<script async src="js/jquery.js"></script>
<script async src="js/bootstrap.js"></script>
</head>
<body>
...
</body>
</html>
Unterschiede bei der Script-Ausführung
Auch BÖSE!
<body>
<style>
.item { color: white; }
<style>
<div class="item" style="background-color: red;"></div>
</body>
Die richtige Reihenfolge der HTML-Struktur
 CSS-Code immer beim Header unterbringen
 Vermeide Embedded und Inline Styles
 JavaScript-Code immer am Ende vom Body
 Ab HTML5 Hilft der async-Tag für die
Verarbeitung zum richtigen Zeitpunkt
Und wieder BÖSE!
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="css/bootstrap.css">
</head>
<body>
...
<script src="js/jquery.js"></script>
<script src="js/bootstrap.js"></script>
</body>
</html>
Gut… 
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="css/bootstrap.min.css">
</head>
<body>
...
<script src="js/jquery.min.js"></script>
<script src="js/bootstrap.min.js"></script>
</body>
</html>
Minifying von Dateien
 Das Laden der Daten ist kürzer
 CSS-Styles werden schneller gerendert
 App-Paket wird kompakter
Falls man Ressourcen nicht lokal ablegen kann, dann
lieber CDN nutzen…
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/...
...3.3.5/css/bootstrap.min.css">
</head>
<body>
...
<script src="https://ajax.googleapis.com/ajax/...
...libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/...
...bootstrap/3.3.5/js/bootstrap.min.js"></script>
</body>
</html>
Das Content Delivery Network (CDN)
 Ressourcen werden automatisch gecached
 jsdelivr.com
Quiz: Welcher Download ist schneller?
a) 10 x 1 KB Große Bilddateien
b) 1 x 10 KB Große Bilddatei
Die Lösung ist B
 Die HTTP-Spezifikation kann nur wenige parallele
Downloadvorgänge ausführen.
CSS Sprite Bilder verwenden
Icons.png: 1 x 13 KB Große Datei
 Alle nötigen Grafiken auf
einem Bild enthalten
 Kommt ursprünglich aus
der Spieleentwicklung
 Ein Download für alle
nötigen Grafiken
 Austausch von Grafiken
ohne Verzögerung
(Flackern)
CSS Sprite Bilder verwenden
240px
40px
40px
Scenario #1 – Multiple Files Scenario #2 - Image Sprite
40px
6 Bilder
6 Verbindungen
96 KB
1 Bild
1 Verbindung
21 KB
40px40px40px40px40px40px
BÖSE!
.iconGlas {
width: 20px;
height: 20px;
background-image: url(img/glas.png);
}
.iconHeart {
width: 20px;
height: 20px;
background-image: url(img/heart.png);
}
Gut… 
.spriteIcon {
width: 20px;
height: 20px;
background-image: url(img/icons.png);
}
.spriteIconGlas {
background-position: 0 0;
}
.spriteIconHeart {
background-position: -90px 0;
}
Quiz: Was ist besser? JPEG oder PNG?
a) JPEG
b) PNG
c) Je nach Anwendungsfall
Die Lösung ist C
 JPEG für Fotografien: Landschaften oder Gesichter
 PNG: Logo, Diagramme, Screenshots (verbraucht mehr
Memory und Decodierung)
 Bitte vermeiden: GIF, TIFF, BMP, WebP, etc.
Bilder vom Download bis zur Anzeige
Okay, die Daten wurden geladen. Was steckt noch
hinter dem Browser?
Zwei „Threads“ teilen sich die Arbeit…
Main Thread
 Er führt den JavaScript-Code aus
 Berechnet HTML-Elemente
 Gemeinsam mit CSS-Styles
(Layouten)
 Verarbeitet die Elemente in Bitmaps
Composition Thread
 Zeichnet Bitmaps mit der GPU
(Circa 60 mal die Sekunde)
 Berechnung der Sichtbaren Elemente
 Berechnung für die Bewegung von
Elementen (Scrollen)
Arbeit für dich
Fertig! Überprüf
mal bitte…
Hier mal bitte
Zeichnen…
NEIN
Nur wenn ich
gerade nichts
zu tun hab!
Web Runtime Architektur
Networking /
Cache
Parsers
1
2 7
43 8 9
5 6
DOM
Tree
Formatting Layout Painting
1
2 7
43 8 9
5 6
Display Tree
Compositing
DOM API
& Capabilities
JavaScript
CSS Cascade
Die meiste Arbeit steckt beim „Reflow“
Okay, verstanden.. Jetzt sind wir bereit für weitere
Top Performance-Tipps!
Gefährliche Animation! Warum?
@keyframes drive {
from {
margin-top: 0px;
margin-left: -400;
}
to {
margin-top: 50px;
margin-left: 200px;
}
}
Erst recht, BÖSE!
$("#element").animate({
"margin-left": "200px",
"margin-top": "50px"
}, 2000);
Finger weg von JQuery!
Perfekt! So geht’s ab… 
@keyframes drive {
from {
transform: translate(-400px, 0px);
}
to {
transform: translate(200px, 50px);
}
}
Animationen GPU beschleunigen mit CSS-Transitions
 Compositor-Thread übernimmt die Animation einmalig,
der Rest wird von der GPU verarbeitet
 Tipp: Anstatt display:none oder
visibility:hidden, mit Transitions die Elemente
außerhalb vom Screen ablegen. Das ist 3-5 x schneller.
Waaahhh!
-ms-gradient(linear, 50% 50%, 0% 34%, from(#666666), to(#666666), color-stop(.3,#333333))
-webkit-gradient(linear, 50% 50%, 0% 34%, from(#666666), to(#666666), color-stop(.3,#333333))
-moz-gradient(linear, 50% 50%, 0% 34%, from(#666666), to(#666666), color-stop(.3,#333333))
gradient(linear, 50% 50%, 0% 34%, from(#666666), to(#666666), color-stop(.3,#333333))
Ein Herz für JPEG! <3
Verwende Bilder anstatt CSS3 Gradients oder
Border Radius
 Bilder werden immer direkt von der GPU verarbeitet
 Am besten JPEG verwenden
EventListener können zu unangenehmen Events führen
function createElements() {
for (var i = 0; i < 100; ++i) {
var xBtn = document.createElement('button');
xBtn.setAttribute('value', 'AA');
xBtn.addEventListener('click', hi, false);
containerDiv.appendChild(xBtn);
xBtn = null;
}
}
function clearElements() {
containerDiv.innerHTML = "";
}
Unnötige EventListener wieder abbestellen
function createElements() {
for (var i = 0; i < 100; ++i) {
var xBtn = document.createElement('button');
xBtn.setAttribute('value', 'AA');
xBtn.addEventListener('click', hi, false);
containerDiv.appendChild(xBtn);
xBtn = null;
}
}
function clearElements() {
var els = containerDiv.childNodes;
for (var i = 0; i < els.length; i++) {
els[i].removeEventListener('click', hi, false);
containerDiv.removeChild(els[i]);
}
}
Zuviel des Guten…
for (i = 0; i < 100; i++){
img[i].addEventListener("click", function clickListener(e) {
var clickedItem = e.target.id;
alert("Hello " + clickedItem);
});
}
Besser: Bubbling Events nutzen
var theParent = document.querySelector("#theDude");
theParent.addEventListener("click", doSomething, false);
function doSomething(e) {
if (e.target !== e.currentTarget) {
var clickedItem = e.target.id;
alert("Hello " + clickedItem);
}
e.stopPropagation();
}
Best Practices für EventListener
 Minimiere unnötige Events
 Teile Events übergreifend wenn möglich
Der Timer vom Performanceteufel…
setInterval(function() {
// Mach irgendwas...
}, 2000);
Im Einklang, mit dem Powerengel…
var start = null;
function step(timestamp) {
if (!start) start = timestamp;
var progress = timestamp - start;
// Mach irgendwas...
if (progress < 2000) {
window.requestAnimationFrame(step);
}
}
window.requestAnimationFrame(step);
Am Rendering festhalten
 Timer unterbricht den Standard Prozess und sorgt für einen Reflow
 window.requestAnimationFrame hängt direkt am Render-
Prozess und ist somit im Einklang vom Standard Prozess
Quiz: Welche Variable bekommt den schnellsten
Zugriff?
var a = 1;
var b = "ich";
var c = 0.1;
var d = 0x1;
Richtig ist A
var a = 1;
var b = "ich";
var c = 0.1;
var d = 0x1;
STACK
0x00000003a:
0x005e4148b:
0x005e4160c:
String
“ich”
Number
0.1
Number
0x1
0x005e4170d:
HEAP
0x005e4148: 0…01001000
0x03 represents 1: 0…00000011
Number in JavaScript
 Alle Zahlen in JavaScript sind IEEE 64-Bit floating numbers
 Gute für den flexiblen Einsatz
 Eine Performance Herausforderung
31bits
31-bit (tagged) Integers
1bit
1
31bits
Object pointer
1bit
0
32bits
32bits
Floats
32-bit Integers
STACK HEAP
FIXE LÄNGE, SCHNELLER ZUGRIFF VARIABLE LÄNGE, LANGSAMER ZUGRIFF
Boxed
Best Practices für Number
 Verwende eine 31-Bit Zahl wenn möglich
 Verwende nur floats wenn nötig
Böses Array! Aber warum?
var bad = new Array();
bad[0] = 1;
bad[1] = 5.6;
bad[2] = "Will nicht böse sein";
Es entstehen Kopien im Speicher und Konvertierungen
var bad = new Array();
bad[0] = 1;
bad[1] = 5.6;
bad[2] = "Will nicht böse sein";
Type: Int Array 1
Type: Float Array
Type: Var Array 1 2.3 “Will..”
1 5.6
Immer noch Schmerzen! Aber warum?
var bad = new Array();
bad[0] = 1;
bad[1] = 5.6;
bad[2] = "Will nicht böse sein";
Pre-allocate Arrays
var bad = new Array();
bad[0] = 1;
bad[1] = 5.6;
bad[2] = "Will nicht böse sein";
var bad = new Array(100);
bad[0] = 1;
bad[1] = 5.6;
bad[2] = "Will nicht böse sein";
0 ?
?+1 ??
Langsam Schnell
…0 100
Verwende Typed Arrays wenn möglich
var value = 5;
var a = new Float64Array(100);
a[0] = value; // 5.0 - no tagging required
a[1] = value / 2; // 2.5 - no boxing required
a[2] = "text"; // 0.0
var a = new Int32Array(100);
a[0] = value; // 5 - no tagging required
a[1] = value / 2; // 2 - no tagging required
a[2] = "text"; // 0
Tödliche Schleifen…
var a = new Array(100);
var total = 0;
for (var item in a) {
total += item;
};
a.forEach(function(item){
total += item;
});
for (var i = 0; i < a.length; i++) {
total += a[i];
}
Nutze eine Schleife effizient
var a = new Array(100);
var total = 0;
var cachedLength = a.length;
for (var i = 0; i < cachedLength; i++) {
total += a[i];
}
Best Practices für Arrays
 Gebe eine fixe Größe mit
 Verwende Typed Arrays wenn möglich
 Nutze eine Schleife effizient
The DOOM of DOM
...
//for each rotation
document.getElementById("myDiv").classList.remove(oldClass)
document.getElementById("myDiv").classList.add(newClass)
...
JavaScript
DOM
DOM Kommunikation findet jetzt nur einmalig statt
var element = document.getElementById(elID).classList;
//for each rotation
element.remove(oldClass)
element.add(newClass)
...
JavaScript
DOM
DOM Kommunikation findet jetzt nur einmalig statt
var elems = ['img1.jpg', … 'img6.jpg'];
var fragment = document.createDocumentFragment();
for (var i=0; i < elems.length; i++) {
var newNode = document.createElement('img');
newNode.setAttribute('src', elems[i]);
fragment.appendChild(newNode);
}
target.appendChild(fragment);
JavaScript
DOM
Mhhh.. Was ist daran schlimm?
this.boardSize = document.getElementById("benchmarkBox").value;
for (var i = 0; i < this.boardSize; i++) {
//this.boardSize is “25”
for (var j = 0; j < this.boardSize; j++) {
//this.boardSize is “25”
...
}
}
DOM-Elemente sind immer ein String.
Ein direktes parseInt ist 25% schneller!
this.boardSize = parseInt(document.getElementById("benchmarkBox").value);
for (var i = 0; i < this.boardSize; i++) {
//this.boardSize is 25
for (var j = 0; j < this.boardSize; j++) {
//this.boardSize is 25
...
}
}
Wollt ihr noch das beste zum Schluss?
Touchverzögerung entfernen mit FastClick
 Bei Klick oder Touch findet
eine 300 ms Verzögerung
statt
 Entfernen mit FastClick
 github.com/ftlabs/fastclick
Vieeeelll besser….
<script src='/path/to/fastclick.js'></script>
...
document.addEventListener('DOMContentLoaded', function() {
FastClick.attach(document.body);
}, false);
Fazit 1 von 3
 Die UI ist für den Benutzer schnell, wenn sie unter 100 ms reagiert
 Setze moderne WebViews für die Hybrid-Apps ein
 Crosswalk und WKWebView
 Verwende eine saubere HTML-Struktur
 Regeln für Head und Body beachten
 Daten müssen schnell bereitstehen
 Styles und Skripte direkt ins App-Paket legen
Fazit 2 von 3
 Verwende die GPU so viel wie nur möglich
 Bilder anstatt CSS Features
 Animationen via transform: translate3D
 Auf JQuery verzichten
 Natives JavaScript nutzen
 Gehe sparsam und durchdacht mit Events um
 Hänge dich an den Render-Prozess für eine Timer-Funktion
 window.requestAnimationFrame
Fazit 3 von 3
 Erspare JavaScript unnötige Arbeit mit Konvertierungen
 Nutze JavaScript Arrays effektiv
 Verwende Schleifen
 Gehe beachtlich mit dem DOM Zugriff um
 Unnötige „Reflows“ ersparen
 Touchverzögerung entfernen
Kostenloses Video-Training für alle!
http://goo.gl/BQb8ul
Kostenloser Artikel auf Entwickler.de für alle!
https://goo.gl/vwWysC
FRAGEN?
http://about.me/Gregor.Biswanger
Ich freue mich auf Feedback!
Vielen Dank!

Aber schnell! Top HTML5 Performance Tipps für Hybrid- und Web-Apps

  • 1.
    Aber schnell! Performanceaspekte inCross-Plattform-HTML5- Anwendungen Gregor Biswanger | CEO von CleverSocial.de, Freier Dozent, Berater, Trainer und Autor about.me/gregor.biswanger
  • 2.
    Bitte warten… Sprecherwird geladen…
  • 3.
    Über mich  Gründervon CleverSocial.de  Freier Dozent, Berater und Trainer  Schwerpunkte .NET-Architektur, Agile Prozesse, XAML, Web und Cloud  Technologieberater für die Intel Developer Zone  Sprecher auf Konferenzen und User Groups  Freier Autor für heise.de, dotnetpro, WindowsDeveloper und viele weitere Fachmagazine  Video-Trainer bei video2brain und Microsoft Gregor Biswanger Microsoft MVP, Intel Black Belt & Intel Software Innovator dotnet-blog.net about.me/gregor.biswanger
  • 4.
    Unsere gemeinsame Reise Performance messen  Welche Probleme gibt es bei Hybrid-Apps  Wie funktioniert der Browser  Zahlreiche Performance-Tipps für Web-Entwickler
  • 5.
  • 6.
  • 7.
  • 8.
    100 ms istein gutes und realistisches Ziel Das ist unser Ziel!
  • 9.
    Was ist ApacheCordova? Wie Hybrid-App Entwicklung mit HTML5?
  • 10.
    Die Lösung: Hybrid-Appsmit Apache Cordova  Cordova ist ein JavaScript-Framework für lokal installierbare WebApps auf mobilen Endgeräten  Ist Open-Source und liegt auf GitHub  Unterstützte Plattformen: iOS, Android, LG webOS, Symbian OS, BlackBerry, Tizen, Firefox OS, Windows Phone, Windows 8  Features  Zugriff auf Sensoren  Plattformspezifische Funktionen (Notifications)  Zugriff auf Kontakte  Zugriff auf lokale Dateien  Cordova bietet kein UI Framework! cordova.apache.org
  • 11.
    Der Cordova Build CloudCompiler JS CSS HTML oder AppsWWW Projekt Local Compiler
  • 12.
    Plattform (Betriebssystem) Native App(Android, WP, iOS) WebView (Browser) Hybrid-App Architektur WWWProjekt Frontend – HTML5 und CSS (Twitter Bootstrap) Backend - JavaScript (Apache Cordova)
  • 13.
    Plattform (Betriebssystem) Native App(Android, WP, iOS) WebView (Browser) Cordova Plugin Architektur Frontend – HTML5 und CSS (Twitter Bootstrap) Backend - JavaScript (Apache Cordova) API Sensoren (Hardware) Plugin Plugin Android und Windows Phone benötigen Zugriffsberechtigungen und/oder Hardware nicht vorhanden.
  • 14.
    Wie können wirdie Performance testen?
  • 15.
    Wichtig! Am bestenauf alten Geräten testen…
  • 16.
    Dann bringt einTest auf neuer Hardware…
  • 17.
    Okay, also eineWeb-Browser-App im Vollbildmodus…
  • 18.
  • 19.
    Das Crosswalk Project Open-Source (BSD Lizenz)  Embedded Chrome Chromium  Für Android und Tizen  Ab Android Version 4  Ab Tizen Version 3  Nachteil: Paketgröße circa 15-20 MB  An Crosswalk Lite wird aktuell gearbeitet  Paketgröße circa 7 MB crosswalk-project.org
  • 20.
    Kostenlos Builden viaIntel XDK xdk.intel.com
  • 21.
    WKWebView  Cordova Plug-In Ersetzt die Standard UIWebView  Ab iOS 8 verfügbar
  • 22.
    Einbinden ganz einfachvia Cordova Plug-In  Über die Plugin ID:  com.telerik.plugins.wkwebview Beim Intel XDK ganz einfach über den Plug-In Manager
  • 23.
    Dann müssen wiranalysieren, wie ein Browser unter der Haube arbeitet…
  • 24.
    Erst wird allesgeladen…
  • 25.
    BÖSE! <!DOCTYPE html> <html> <head> <link rel="stylesheet"href="css/bootstrap.css"> <script src="js/jquery.js"></script> <script src="js/bootstrap.js"></script> </head> <body> ... </body> </html>
  • 26.
    Gut…  <!DOCTYPE html> <html> <head> <linkrel="stylesheet" href="css/bootstrap.css"> </head> <body> ... <script src="js/jquery.js"></script> <script src="js/bootstrap.js"></script> </body> </html>
  • 27.
    Get auch fürHTML5 Browser mit async-Tag… <!DOCTYPE html> <html> <head> <link rel="stylesheet" href="css/bootstrap.css"> <script async src="js/jquery.js"></script> <script async src="js/bootstrap.js"></script> </head> <body> ... </body> </html>
  • 28.
    Unterschiede bei derScript-Ausführung
  • 29.
    Auch BÖSE! <body> <style> .item {color: white; } <style> <div class="item" style="background-color: red;"></div> </body>
  • 30.
    Die richtige Reihenfolgeder HTML-Struktur  CSS-Code immer beim Header unterbringen  Vermeide Embedded und Inline Styles  JavaScript-Code immer am Ende vom Body  Ab HTML5 Hilft der async-Tag für die Verarbeitung zum richtigen Zeitpunkt
  • 31.
    Und wieder BÖSE! <!DOCTYPEhtml> <html> <head> <link rel="stylesheet" href="css/bootstrap.css"> </head> <body> ... <script src="js/jquery.js"></script> <script src="js/bootstrap.js"></script> </body> </html>
  • 32.
    Gut…  <!DOCTYPE html> <html> <head> <linkrel="stylesheet" href="css/bootstrap.min.css"> </head> <body> ... <script src="js/jquery.min.js"></script> <script src="js/bootstrap.min.js"></script> </body> </html>
  • 33.
    Minifying von Dateien Das Laden der Daten ist kürzer  CSS-Styles werden schneller gerendert  App-Paket wird kompakter
  • 34.
    Falls man Ressourcennicht lokal ablegen kann, dann lieber CDN nutzen… <!DOCTYPE html> <html> <head> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/... ...3.3.5/css/bootstrap.min.css"> </head> <body> ... <script src="https://ajax.googleapis.com/ajax/... ...libs/jquery/1.11.3/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/... ...bootstrap/3.3.5/js/bootstrap.min.js"></script> </body> </html>
  • 35.
    Das Content DeliveryNetwork (CDN)  Ressourcen werden automatisch gecached  jsdelivr.com
  • 36.
    Quiz: Welcher Downloadist schneller? a) 10 x 1 KB Große Bilddateien b) 1 x 10 KB Große Bilddatei
  • 37.
    Die Lösung istB  Die HTTP-Spezifikation kann nur wenige parallele Downloadvorgänge ausführen.
  • 38.
    CSS Sprite Bilderverwenden Icons.png: 1 x 13 KB Große Datei  Alle nötigen Grafiken auf einem Bild enthalten  Kommt ursprünglich aus der Spieleentwicklung  Ein Download für alle nötigen Grafiken  Austausch von Grafiken ohne Verzögerung (Flackern)
  • 39.
    CSS Sprite Bilderverwenden 240px 40px 40px Scenario #1 – Multiple Files Scenario #2 - Image Sprite 40px 6 Bilder 6 Verbindungen 96 KB 1 Bild 1 Verbindung 21 KB 40px40px40px40px40px40px
  • 40.
    BÖSE! .iconGlas { width: 20px; height:20px; background-image: url(img/glas.png); } .iconHeart { width: 20px; height: 20px; background-image: url(img/heart.png); }
  • 41.
    Gut…  .spriteIcon { width:20px; height: 20px; background-image: url(img/icons.png); } .spriteIconGlas { background-position: 0 0; } .spriteIconHeart { background-position: -90px 0; }
  • 42.
    Quiz: Was istbesser? JPEG oder PNG? a) JPEG b) PNG c) Je nach Anwendungsfall
  • 43.
    Die Lösung istC  JPEG für Fotografien: Landschaften oder Gesichter  PNG: Logo, Diagramme, Screenshots (verbraucht mehr Memory und Decodierung)  Bitte vermeiden: GIF, TIFF, BMP, WebP, etc.
  • 44.
    Bilder vom Downloadbis zur Anzeige
  • 45.
    Okay, die Datenwurden geladen. Was steckt noch hinter dem Browser?
  • 46.
    Zwei „Threads“ teilensich die Arbeit… Main Thread  Er führt den JavaScript-Code aus  Berechnet HTML-Elemente  Gemeinsam mit CSS-Styles (Layouten)  Verarbeitet die Elemente in Bitmaps Composition Thread  Zeichnet Bitmaps mit der GPU (Circa 60 mal die Sekunde)  Berechnung der Sichtbaren Elemente  Berechnung für die Bewegung von Elementen (Scrollen) Arbeit für dich Fertig! Überprüf mal bitte… Hier mal bitte Zeichnen… NEIN Nur wenn ich gerade nichts zu tun hab!
  • 47.
    Web Runtime Architektur Networking/ Cache Parsers 1 2 7 43 8 9 5 6 DOM Tree Formatting Layout Painting 1 2 7 43 8 9 5 6 Display Tree Compositing DOM API & Capabilities JavaScript CSS Cascade
  • 48.
    Die meiste Arbeitsteckt beim „Reflow“
  • 49.
    Okay, verstanden.. Jetztsind wir bereit für weitere Top Performance-Tipps!
  • 50.
    Gefährliche Animation! Warum? @keyframesdrive { from { margin-top: 0px; margin-left: -400; } to { margin-top: 50px; margin-left: 200px; } }
  • 51.
    Erst recht, BÖSE! $("#element").animate({ "margin-left":"200px", "margin-top": "50px" }, 2000);
  • 52.
  • 53.
    Perfekt! So geht’sab…  @keyframes drive { from { transform: translate(-400px, 0px); } to { transform: translate(200px, 50px); } }
  • 54.
    Animationen GPU beschleunigenmit CSS-Transitions  Compositor-Thread übernimmt die Animation einmalig, der Rest wird von der GPU verarbeitet  Tipp: Anstatt display:none oder visibility:hidden, mit Transitions die Elemente außerhalb vom Screen ablegen. Das ist 3-5 x schneller.
  • 55.
    Waaahhh! -ms-gradient(linear, 50% 50%,0% 34%, from(#666666), to(#666666), color-stop(.3,#333333)) -webkit-gradient(linear, 50% 50%, 0% 34%, from(#666666), to(#666666), color-stop(.3,#333333)) -moz-gradient(linear, 50% 50%, 0% 34%, from(#666666), to(#666666), color-stop(.3,#333333)) gradient(linear, 50% 50%, 0% 34%, from(#666666), to(#666666), color-stop(.3,#333333))
  • 56.
    Ein Herz fürJPEG! <3
  • 57.
    Verwende Bilder anstattCSS3 Gradients oder Border Radius  Bilder werden immer direkt von der GPU verarbeitet  Am besten JPEG verwenden
  • 58.
    EventListener können zuunangenehmen Events führen function createElements() { for (var i = 0; i < 100; ++i) { var xBtn = document.createElement('button'); xBtn.setAttribute('value', 'AA'); xBtn.addEventListener('click', hi, false); containerDiv.appendChild(xBtn); xBtn = null; } } function clearElements() { containerDiv.innerHTML = ""; }
  • 59.
    Unnötige EventListener wiederabbestellen function createElements() { for (var i = 0; i < 100; ++i) { var xBtn = document.createElement('button'); xBtn.setAttribute('value', 'AA'); xBtn.addEventListener('click', hi, false); containerDiv.appendChild(xBtn); xBtn = null; } } function clearElements() { var els = containerDiv.childNodes; for (var i = 0; i < els.length; i++) { els[i].removeEventListener('click', hi, false); containerDiv.removeChild(els[i]); } }
  • 60.
    Zuviel des Guten… for(i = 0; i < 100; i++){ img[i].addEventListener("click", function clickListener(e) { var clickedItem = e.target.id; alert("Hello " + clickedItem); }); }
  • 61.
    Besser: Bubbling Eventsnutzen var theParent = document.querySelector("#theDude"); theParent.addEventListener("click", doSomething, false); function doSomething(e) { if (e.target !== e.currentTarget) { var clickedItem = e.target.id; alert("Hello " + clickedItem); } e.stopPropagation(); }
  • 62.
    Best Practices fürEventListener  Minimiere unnötige Events  Teile Events übergreifend wenn möglich
  • 63.
    Der Timer vomPerformanceteufel… setInterval(function() { // Mach irgendwas... }, 2000);
  • 64.
    Im Einklang, mitdem Powerengel… var start = null; function step(timestamp) { if (!start) start = timestamp; var progress = timestamp - start; // Mach irgendwas... if (progress < 2000) { window.requestAnimationFrame(step); } } window.requestAnimationFrame(step);
  • 65.
    Am Rendering festhalten Timer unterbricht den Standard Prozess und sorgt für einen Reflow  window.requestAnimationFrame hängt direkt am Render- Prozess und ist somit im Einklang vom Standard Prozess
  • 66.
    Quiz: Welche Variablebekommt den schnellsten Zugriff? var a = 1; var b = "ich"; var c = 0.1; var d = 0x1;
  • 67.
    Richtig ist A vara = 1; var b = "ich"; var c = 0.1; var d = 0x1; STACK 0x00000003a: 0x005e4148b: 0x005e4160c: String “ich” Number 0.1 Number 0x1 0x005e4170d: HEAP 0x005e4148: 0…01001000 0x03 represents 1: 0…00000011
  • 68.
    Number in JavaScript Alle Zahlen in JavaScript sind IEEE 64-Bit floating numbers  Gute für den flexiblen Einsatz  Eine Performance Herausforderung 31bits 31-bit (tagged) Integers 1bit 1 31bits Object pointer 1bit 0 32bits 32bits Floats 32-bit Integers STACK HEAP FIXE LÄNGE, SCHNELLER ZUGRIFF VARIABLE LÄNGE, LANGSAMER ZUGRIFF Boxed
  • 69.
    Best Practices fürNumber  Verwende eine 31-Bit Zahl wenn möglich  Verwende nur floats wenn nötig
  • 70.
    Böses Array! Aberwarum? var bad = new Array(); bad[0] = 1; bad[1] = 5.6; bad[2] = "Will nicht böse sein";
  • 71.
    Es entstehen Kopienim Speicher und Konvertierungen var bad = new Array(); bad[0] = 1; bad[1] = 5.6; bad[2] = "Will nicht böse sein"; Type: Int Array 1 Type: Float Array Type: Var Array 1 2.3 “Will..” 1 5.6
  • 72.
    Immer noch Schmerzen!Aber warum? var bad = new Array(); bad[0] = 1; bad[1] = 5.6; bad[2] = "Will nicht böse sein";
  • 73.
    Pre-allocate Arrays var bad= new Array(); bad[0] = 1; bad[1] = 5.6; bad[2] = "Will nicht böse sein"; var bad = new Array(100); bad[0] = 1; bad[1] = 5.6; bad[2] = "Will nicht böse sein"; 0 ? ?+1 ?? Langsam Schnell …0 100
  • 74.
    Verwende Typed Arrayswenn möglich var value = 5; var a = new Float64Array(100); a[0] = value; // 5.0 - no tagging required a[1] = value / 2; // 2.5 - no boxing required a[2] = "text"; // 0.0 var a = new Int32Array(100); a[0] = value; // 5 - no tagging required a[1] = value / 2; // 2 - no tagging required a[2] = "text"; // 0
  • 75.
    Tödliche Schleifen… var a= new Array(100); var total = 0; for (var item in a) { total += item; }; a.forEach(function(item){ total += item; }); for (var i = 0; i < a.length; i++) { total += a[i]; }
  • 76.
    Nutze eine Schleifeeffizient var a = new Array(100); var total = 0; var cachedLength = a.length; for (var i = 0; i < cachedLength; i++) { total += a[i]; }
  • 77.
    Best Practices fürArrays  Gebe eine fixe Größe mit  Verwende Typed Arrays wenn möglich  Nutze eine Schleife effizient
  • 78.
    The DOOM ofDOM ... //for each rotation document.getElementById("myDiv").classList.remove(oldClass) document.getElementById("myDiv").classList.add(newClass) ... JavaScript DOM
  • 79.
    DOM Kommunikation findetjetzt nur einmalig statt var element = document.getElementById(elID).classList; //for each rotation element.remove(oldClass) element.add(newClass) ... JavaScript DOM
  • 80.
    DOM Kommunikation findetjetzt nur einmalig statt var elems = ['img1.jpg', … 'img6.jpg']; var fragment = document.createDocumentFragment(); for (var i=0; i < elems.length; i++) { var newNode = document.createElement('img'); newNode.setAttribute('src', elems[i]); fragment.appendChild(newNode); } target.appendChild(fragment); JavaScript DOM
  • 81.
    Mhhh.. Was istdaran schlimm? this.boardSize = document.getElementById("benchmarkBox").value; for (var i = 0; i < this.boardSize; i++) { //this.boardSize is “25” for (var j = 0; j < this.boardSize; j++) { //this.boardSize is “25” ... } }
  • 82.
    DOM-Elemente sind immerein String. Ein direktes parseInt ist 25% schneller! this.boardSize = parseInt(document.getElementById("benchmarkBox").value); for (var i = 0; i < this.boardSize; i++) { //this.boardSize is 25 for (var j = 0; j < this.boardSize; j++) { //this.boardSize is 25 ... } }
  • 83.
    Wollt ihr nochdas beste zum Schluss?
  • 84.
    Touchverzögerung entfernen mitFastClick  Bei Klick oder Touch findet eine 300 ms Verzögerung statt  Entfernen mit FastClick  github.com/ftlabs/fastclick
  • 85.
  • 86.
    Fazit 1 von3  Die UI ist für den Benutzer schnell, wenn sie unter 100 ms reagiert  Setze moderne WebViews für die Hybrid-Apps ein  Crosswalk und WKWebView  Verwende eine saubere HTML-Struktur  Regeln für Head und Body beachten  Daten müssen schnell bereitstehen  Styles und Skripte direkt ins App-Paket legen
  • 87.
    Fazit 2 von3  Verwende die GPU so viel wie nur möglich  Bilder anstatt CSS Features  Animationen via transform: translate3D  Auf JQuery verzichten  Natives JavaScript nutzen  Gehe sparsam und durchdacht mit Events um  Hänge dich an den Render-Prozess für eine Timer-Funktion  window.requestAnimationFrame
  • 88.
    Fazit 3 von3  Erspare JavaScript unnötige Arbeit mit Konvertierungen  Nutze JavaScript Arrays effektiv  Verwende Schleifen  Gehe beachtlich mit dem DOM Zugriff um  Unnötige „Reflows“ ersparen  Touchverzögerung entfernen
  • 89.
    Kostenloses Video-Training füralle! http://goo.gl/BQb8ul
  • 90.
    Kostenloser Artikel aufEntwickler.de für alle! https://goo.gl/vwWysC
  • 91.
  • 92.