Performances

Post on 22-Jun-2015

1.159 views 2 download

description

Cours sur les performances côté client.

Transcript of Performances

Performances client

Performances client ?

Malgré l’augmentation des débits,le web est lent

Site web Temps de chargement

TF1 5,0s

Allociné 4,0s

Facebook 4,6s

Skyrock 3,7s

Yahoo! France 1,8s

DailyMotion 2,4s

Le Monde 7,9s

Amazon France 3,7s

Depuis 5 ans…

Depuis 5 ans…

• Poids des pages x3

Depuis 5 ans…

• Poids des pages x3

• Nombre de composants x2

Depuis 5 ans…

• Poids des pages x3

• Nombre de composants x2

• Nombre de balises HTML x2

Depuis 5 ans…

• Poids des pages x3

• Nombre de composants x2

• Nombre de balises HTML x2

En moyenne, plus de 300 ko par page… pour seulement 500 mots

Depuis 5 ans…

• Poids des pages x3

• Nombre de composants x2

• Nombre de balises HTML x2

En moyenne, plus de 300 ko par page… pour seulement 500 mots

Source

Est-ce utile ?

Est-ce utile ?

• 500ms = -20% de traffic pour Google

Est-ce utile ?

• 500ms = -20% de traffic pour Google

• 100ms = -1% de ventes pour Amazon

Est-ce utile ?

• 500ms = -20% de traffic pour Google

• 100ms = -1% de ventes pour Amazon

• -30% du poids = +25% d’utilisateurs pour Google Maps

Est-ce utile ?

• 500ms = -20% de traffic pour Google

• 100ms = -1% de ventes pour Amazon

• -30% du poids = +25% d’utilisateurs pour Google Maps

• 400ms = 5 à 9% d'abandons pour Yahoo!

Pourquoi le client ?

Pourquoi le client ?

Pourquoi le client ?

Pourquoi le client ?

Pourquoi le client ?

80 à 90% du chargement géré par le client10 à 20% pour l’applicatif serveur

Un peu de réseau

Le mythe de l’ADSLOffres 8, 20, 28 Mbits

Le mythe de l’ADSL(ATM)Offres 8, 20, 28 Mbits

Le mythe de l’ADSL(ATM)Offres 8, 20, 28 Mbits

Pour 8 Mbits :

Le mythe de l’ADSL(ATM)Offres 8, 20, 28 Mbits

-20% à -25% : 6 Mbits en IPPour 8 Mbits :

Le mythe de l’ADSL(ATM)Offres 8, 20, 28 Mbits

-20% à -25% : 6 Mbits en IP-2% à -3% : 5,8 Mbits en TCP/IP

Pour 8 Mbits :

Le mythe de l’ADSL(ATM)Offres 8, 20, 28 Mbits

-20% à -25% : 6 Mbits en IP-2% à -3% : 5,8 Mbits en TCP/IP

Pour 8 Mbits :

Débit théorique maximal sur une ligne optimale

Le mythe de l’ADSL(ATM)Offres 8, 20, 28 Mbits

-20% à -25% : 6 Mbits en IP-2% à -3% : 5,8 Mbits en TCP/IP

Pour 8 Mbits :

Débit théorique maximal sur une ligne optimaleTV par ADSL : 5Mbits

Le mythe de l’ADSL(ATM)Offres 8, 20, 28 Mbits

-20% à -25% : 6 Mbits en IP-2% à -3% : 5,8 Mbits en TCP/IP

Pour 8 Mbits :

Débit théorique maximal sur une ligne optimaleTV par ADSL : 5Mbits

Il y a encore du RTC en France

Le mythe de l’ADSL(ATM)Offres 8, 20, 28 Mbits

-20% à -25% : 6 Mbits en IP-2% à -3% : 5,8 Mbits en TCP/IP

Pour 8 Mbits :

Débit théorique maximal sur une ligne optimale

3G : 3,6Mbits théorique (~2Mbits en pratique)

TV par ADSL : 5Mbits

Il y a encore du RTC en France

Chargement d’une ressource

Chargement d’une ressource

Navigateur

Chargement d’une ressource

Navigateur

Temps

Chargement d’une ressource

Serveur DNS

Navigateur

Temps

Chargement d’une ressource

Serveur DNS

Navigateur

Temps

Chargement d’une ressource

Serveur DNS

Navigateur

Temps

DNS

Chargement d’une ressource

Serveur DNS

Navigateur

Serveur

Temps

DNS

Chargement d’une ressource

Serveur DNS

Navigateur

Serveur

Temps

DNS

Chargement d’une ressource

Serveur DNS

Navigateur

Serveur

Temps

DNS TCP

HTT

P

Chargement d’une ressource

Serveur DNS

Navigateur

Serveur

Temps

DNS TCP

Réponse HTTP

HTT

P

Chargement d’une ressource

Serveur DNS

Navigateur

Serveur

Temps

DNS TCP

Réponse HTTP

HTT

P

Chargement d’une ressource

Serveur DNS

Navigateur

Serveur

Temps

DNS TCP

x nombrede domaine

Réponse HTTP

HTT

P

Chargement d’une ressource

Serveur DNS

Navigateur

Serveur

Temps

DNS TCP

x nombrede domaine

x nombre de ressource

Évaluer les performances

• YSlow + Firebug

• WebPageTest

Outils

Agir

Chargement d’une page

Chargement d’une page

• HTML

Chargement d’une page

• HTML

• Images

Chargement d’une page

• HTML

• Images

• CSS

Chargement d’une page

• HTML

• Images

• CSS

• Images CSS

Chargement d’une page

• HTML

• Images

• CSS

• Images CSS

• Javascript

Chargement d’une page

• HTML

• Images

• CSS

• Images CSS

• Javascript

• Exécution

Chargement d’une page

• HTML

• Images

• CSS

• Images CSS

• Javascript

• Exécution

• Rendu

Objectifs

Objectifs

• Moins de requête HTTP

Objectifs

• Moins de requête HTTP

• Ressources moins lourdes

Objectifs

• Moins de requête HTTP

• Ressources moins lourdes

• Améliorer le temps de traitement

static.example.org

static.example.org

• Domaine ou sous-domaine dédié aux ressources statiques

static.example.org

• Domaine ou sous-domaine dédié aux ressources statiques

• Paralléliser les téléchargements

static.example.org

• Domaine ou sous-domaine dédié aux ressources statiques

• Paralléliser les téléchargements

• Désactiver les cookies

static.example.org

• Domaine ou sous-domaine dédié aux ressources statiques

• Paralléliser les téléchargements

• Désactiver les cookies

• Entre 2 et 4 domaines/sous-domaines, pas plus

Toutes ressources

Toutes ressources• Expiration

<IfModule mod_expires.c> ExpiresActive On ExpiresDefault "access plus 1 month" ExpiresByType text/css "access plus 2 weeks"</IfModule>

Toutes ressources• Expiration

<IfModule mod_expires.c> ExpiresActive On ExpiresDefault "access plus 1 month" ExpiresByType text/css "access plus 2 weeks"</IfModule>

• ETagETag: "10C24BC-4AB-457E1C1F"

Par défaut : FileETag INode MTime Size

Désactiver : FileETag None

Ressources texte

Ressources texte

• GZip<IfModule mod_deflate.c> AddOutputFilterByType DEFLATE text/css</IfModule>

HTML

HTML

• Cache serveur

HTML

• Cache serveur

• Réduisez le nombre d’éléments

HTML

• Cache serveur

• Réduisez le nombre d’élémentsdocument.getElementsByTagName('*').length

CSS & Javascript

CSS & Javascript

• CSS : au début

CSS & Javascript

• CSS : au début

• Javascript : à la fin

CSS & Javascript

• CSS : au début

• Javascript : à la fin

CSS & Javascript

• CSS : au début

• Javascript : à la fin

1. Externalisez

CSS & Javascript

• CSS : au début

• Javascript : à la fin

1. Externalisez

2. Combinez

CSS & Javascript

• CSS : au début

• Javascript : à la fin

1. Externalisez

2. Combinez

3. Minimifiez

« Minimification »

« Minimification »

43471 octets 9431 octets

« Minimification »

43471 octets 9431 octets

~ -78%

GZip

43471 octets 12920 octets

GZip

43471 octets 12920 octets

~ -70%

« Minimification » + GZip

43471 octets 3867 octets

« Minimification » + GZip

43471 octets 3867 octets

~ -91%

Javascript

Javascript• N’utilisez pas de packer

Javascript• N’utilisez pas de packer

• Évitez les fichiers dupliqués

Javascript• N’utilisez pas de packer

• Évitez les fichiers dupliqués

• Utilisez intelligemment les événements

Javascript• N’utilisez pas de packer

• Évitez les fichiers dupliqués

• Utilisez intelligemment les événements

• Rendez l’Ajax « cachable »

Javascript• N’utilisez pas de packer

• Évitez les fichiers dupliqués

• Utilisez intelligemment les événements

• Rendez l’Ajax « cachable »

• Minimifiez + GZip

Javascript• N’utilisez pas de packer

• Évitez les fichiers dupliqués

• Utilisez intelligemment les événements

• Rendez l’Ajax « cachable »

• Minimifiez + GZip

• Attention aux requêtes DNS

Javascript• N’utilisez pas de packer

• Évitez les fichiers dupliqués

• Utilisez intelligemment les événements

• Rendez l’Ajax « cachable »

• Minimifiez + GZip

• Attention aux requêtes DNS

• Évitez les redirections

Javascript• N’utilisez pas de packer

• Évitez les fichiers dupliqués

• Utilisez intelligemment les événements

• Rendez l’Ajax « cachable »

• Minimifiez + GZip

• Attention aux requêtes DNS

• Évitez les redirections

• Configurez les ETag

Javascripteval() is evil

Javascripteval() is evil

NON

Javascript

new Boolean(); // Argl…new Number(); // Stop…new String(); // Je souffrenew Object(); // Arrêtez…new Array(); // C'en est tropnew Function(); // PAN!

var bool = false;var nb = 0;var str = "";var obj = {};var array = [];var fn = function() {};

new is evil

JavascriptOptimisez vos boucles

Javascript

var users = []; // 1000+ itemsfor (var i = 0; i < users.length; i++) { … }

Optimisez vos boucles

Javascript

var users = []; // 1000+ itemsfor (var i = 0; i < users.length; i++) { … }

Optimisez vos boucles

for (var i = 0, j = users.length; i < j; i++) { … }

JavascriptAttention aux fonctions anonymes

JavascriptAttention aux fonctions anonymes

$(…).click(function(e) { … }); // jQuery stylevar fn = function(a, b) { return a * b; };

JavascriptAttention aux fonctions anonymes

// Mieux !function fn(a, b) { return a * b; }

$(…).click(function(e) { … }); // jQuery stylevar fn = function(a, b) { return a * b; };

JavascriptAttention aux fonctions anonymes

// Mieux !function fn(a, b) { return a * b; }

$(…).click(function(e) { … }); // jQuery stylevar fn = function(a, b) { return a * b; };

var fn = function fn(a, b) { return a * b; };var obj = { fn: function fn(a, b) { return a * b; }}

JavascriptPré-compiler les RegExp

for (var index = 0, l = links.length; index < l; index++) { if (links[index].href.match(/www\.mydomain\.tld/i)) { // … }}

JavascriptPré-compiler les RegExp

JavascriptPré-compiler les RegExp

var rDomain = /www\.mydomain\.tld/i;for (var index = 0, l = links.length; index < l; index++) { if (links[index].href.match(rDomain)) { // … }}

JavascriptPré-compiler les RegExp

var rDomain = /www\.mydomain\.tld/i;for (var index = 0, l = links.length; index < l; index++) { if (rDomain.test(links[index].href)) { // … }}

Javascriptlength est aussi un setter

Javascriptlength est aussi un setter

var names = ["Geoffrey", "Lorraine", "Thomas", "Clément", "Julien", "Vincent", "Elodie", "Bruno", "Derek", "Lina", "Cyril", "Matti", "Thomas", "Estelle", "Ludovic", "Cédric", "Laurent", "Benjamin", "Mathieu", "Michel", "Kris", "Joffrey", "Alexandre", "Surya", "Antoine", "Ornella", "Simon", "Pierre", "Julien", "Jérémy", "Stéphane", "Arnaud", "Florent", "Albéric", "Julien", "Michaël", "Arnaud", "Dimitri", "Sylvain", "Alexandre", "Thomas", "François", "Robin", "Tugdual", "Prakash", "Carine", "Thomas", "Grégory", "Jean-Kamal", "Anand", "Loïc", "Xavier", "Guillaume", "Damien", "Adrien", "Antoine", "Lucas", "Romain", "Charles", "Loïc", "Maxime", "Gaëtan", "Clément", "Jean-Michel", "Hedi", "Lydie", "Raphaël", "Maxime", "Ludovic", "Audrey", "Frédéric"];

Javascriptlength est aussi un setter

var names = ["Geoffrey", "Lorraine", "Thomas", "Clément", "Julien", "Vincent", "Elodie", "Bruno", "Derek", "Lina", "Cyril", "Matti", "Thomas", "Estelle", "Ludovic", "Cédric", "Laurent", "Benjamin", "Mathieu", "Michel", "Kris", "Joffrey", "Alexandre", "Surya", "Antoine", "Ornella", "Simon", "Pierre", "Julien", "Jérémy", "Stéphane", "Arnaud", "Florent", "Albéric", "Julien", "Michaël", "Arnaud", "Dimitri", "Sylvain", "Alexandre", "Thomas", "François", "Robin", "Tugdual", "Prakash", "Carine", "Thomas", "Grégory", "Jean-Kamal", "Anand", "Loïc", "Xavier", "Guillaume", "Damien", "Adrien", "Antoine", "Lucas", "Romain", "Charles", "Loïc", "Maxime", "Gaëtan", "Clément", "Jean-Michel", "Hedi", "Lydie", "Raphaël", "Maxime", "Ludovic", "Audrey", "Frédéric"];

names.slice(0, 10); // Biennames.length = 10; // Super rapide

Javascriptlength est aussi un setter

var names = ["Geoffrey", "Lorraine", "Thomas", "Clément", "Julien", "Vincent", "Elodie", "Bruno", "Derek", "Lina", "Cyril", "Matti", "Thomas", "Estelle", "Ludovic", "Cédric", "Laurent", "Benjamin", "Mathieu", "Michel", "Kris", "Joffrey", "Alexandre", "Surya", "Antoine", "Ornella", "Simon", "Pierre", "Julien", "Jérémy", "Stéphane", "Arnaud", "Florent", "Albéric", "Julien", "Michaël", "Arnaud", "Dimitri", "Sylvain", "Alexandre", "Thomas", "François", "Robin", "Tugdual", "Prakash", "Carine", "Thomas", "Grégory", "Jean-Kamal", "Anand", "Loïc", "Xavier", "Guillaume", "Damien", "Adrien", "Antoine", "Lucas", "Romain", "Charles", "Loïc", "Maxime", "Gaëtan", "Clément", "Jean-Michel", "Hedi", "Lydie", "Raphaël", "Maxime", "Ludovic", "Audrey", "Frédéric"];

names = []; // Biennames.length = 0; // Terriblement rapide

names.slice(0, 10); // Biennames.length = 10; // Super rapide

Javascriptobj.x === obj["x"]

Javascriptobj.x === obj["x"]

var angle = 60, result;if (useSin) { result = Math.sin(angle);} else { result = Math.cos(angle);}return result;

Javascriptobj.x === obj["x"]

var angle = 60;if (useSin) { return Math.sin(angle);} else { return Math.cos(angle);}

Javascriptobj.x === obj["x"]

var angle = 60;return (useSin) ? Math.sin(angle) : Math.cos(angle);

Javascriptobj.x === obj["x"]

return Math[useSin ? "sin" : "cos"](60);

JavascriptMicro-optimisations

Javascript

var a = 1;var b = 2;

var a = 1, b = 2;

Micro-optimisations

Javascript

times = times || 3;times |= 3; // Valeur numérique uniquement

var a = 1;var b = 2;

var a = 1, b = 2;

Micro-optimisations

JavascriptMicro-optimisations

Javascript

if (value == 3) {}if (value === 3) {}

Micro-optimisations

Javascript

if (1 == 1 || true) {}if (true || 1 == 1) {}

if (value == 3) {}if (value === 3) {}

Micro-optimisations

Javascript

new Date().getTime()

if (1 == 1 || true) {}if (true || 1 == 1) {}

if (value == 3) {}if (value === 3) {}

Micro-optimisations

Javascript

new Date().getTime()Date.now()

if (1 == 1 || true) {}if (true || 1 == 1) {}

if (value == 3) {}if (value === 3) {}

Micro-optimisations

Javascript

new Date().getTime()Date.now()+new Date

if (1 == 1 || true) {}if (true || 1 == 1) {}

if (value == 3) {}if (value === 3) {}

Micro-optimisations

JavascriptMicro-optimisations

JavascriptMicro-optimisations

delete obj.x

JavascriptMicro-optimisations

delete obj.x

objet.tres.interessant.mais.bien.cache

JavascriptUtilisez DocumentFragment

var fragment = document.createDocumentFragment();var div = document.createElement('div');…fragment.appendChild(div);

document.getElementById('box') .appendChild(fragment.cloneNode(true));

JavascriptMinimisez les accès au DOM

$('#box a').click(…);$('#box a').addClass(…);$('#box a').attr(…);

var box = $('#box a');box.click(…);box.addClass(…);box.attr(…);

CSS

CSS

• Évitez filter

CSS

• Évitez filter

• Évitez @import

CSS

• Évitez filter

• Évitez @import

• Évitez expression

CSS

• Évitez filter

• Évitez @import

• Évitez expression

• Évitez les reflows

CSS

• Évitez filter

• Évitez @import

• Évitez expression

• Évitez les reflows

• Optimisez les sélecteurs

CSS

• Évitez filter

• Évitez @import

• Évitez expression

• Évitez les reflows

• Optimisez les sélecteurs

#box .footer ul li a span

CSS

• Évitez filter

• Évitez @import

• Évitez expression

• Évitez les reflows

• Optimisez les sélecteurs

#box .footer ul li a span .footer-link span

Images

• Pas de GIF

• Optimisez les images

• Supprimez les metas (smush.it, pngcrush, jpegtrans)

Images

• Pas de GIF

• Optimisez les images

• Supprimez les metas (smush.it, pngcrush, jpegtrans)

+ =PNG24 (3932 octets)

Images

• Pas de GIF

• Optimisez les images

• Supprimez les metas (smush.it, pngcrush, jpegtrans)

+ =PNG24 (3932 octets)

+ =PNG8 64 couleurs (661 octets)

Images

• Pas de GIF

• Optimisez les images

• Supprimez les metas (smush.it, pngcrush, jpegtrans)

+ =PNG24 (3932 octets)

+ =PNG8 64 couleurs (661 octets)

+ =PNG8 64 couleurs (673 octets)

Images

• Pas de GIF

• Optimisez les images

• Supprimez les metas (smush.it, pngcrush, jpegtrans)

+ =PNG24 (3932 octets)

+ =PNG8 64 couleurs (661 octets)

+ =PNG8 64 couleurs (673 octets)

PNG8 64 couleurs (673 octets)

Images

• Pas de GIF

• Optimisez les images

• Supprimez les metas (smush.it, pngcrush, jpegtrans)

+ =PNG24 (3932 octets)

+ =PNG8 64 couleurs (661 octets)

+ =PNG8 64 couleurs (673 octets)

PNG8 64 couleurs (673 octets) PNG8 64 couleurs (628 octets)

Images

• Pas de GIF

• Optimisez les images

• Supprimez les metas (smush.it, pngcrush, jpegtrans)

+ =PNG24 (3932 octets)

+ =PNG8 64 couleurs (661 octets)

+ =PNG8 64 couleurs (673 octets)

PNG8 64 couleurs (673 octets) PNG8 64 couleurs (628 octets)

- 6,7%

Images

Images

• Spécifiez les dimensions

Images

• Spécifiez les dimensions

• Ne les redimensionnez pas

Images

• Spécifiez les dimensions

• Ne les redimensionnez pas

• Utilisez les sprites

Favicon

Favicon

• Pensez-y, évite une 404

Favicon

• Pensez-y, évite une 404

• Image/icone optimisée

En général

En général

✓ Faites le moins de requête DNS

En général

✓ Faites le moins de requête DNS

✓ Faites le moins de requête HTTP

En général

✓ Faites le moins de requête DNS

✓ Faites le moins de requête HTTP

✓ Évitez les redirections

En général

✓ Faites le moins de requête DNS

✓ Faites le moins de requête HTTP

✓ Évitez les redirections

✓ Évitez les 404

Ressources (outils)• Firebug http://getfirebug.com

• YSlow http://developer.yahoo.com/yslow/

• WebPagetest http://www.webpagetest.org

• Yottaa http://www.yottaa.com

• YUI Compressor http://developer.yahoo.com/yui/compressor/

• Smush.it http://www.smushit.com/ysmush.it/

• SpriteMe http://spriteme.org

Ressources• Comprendre le cache

http://www.mnot.net/cache_docs/index.fr.html

• Performance Playground http://jsperf.com

• Éric Daspet http://performance.survol.fr

• Stoyan Stephanov http://www.phpied.com

• Steve Souders http://www.stevesouders.com/blog/