Performances
description
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/