<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Performance web &#187; réseau</title>
	<atom:link href="http://performance.survol.fr/avec/reseau/feed/" rel="self" type="application/rss+xml" />
	<link>http://performance.survol.fr</link>
	<description>Quelques mots pour des sites web rapides</description>
	<lastBuildDate>Fri, 18 Jun 2010 12:47:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Latence et CDN</title>
		<link>http://performance.survol.fr/2009/06/latence-et-cdn/</link>
		<comments>http://performance.survol.fr/2009/06/latence-et-cdn/#comments</comments>
		<pubDate>Wed, 03 Jun 2009 11:00:57 +0000</pubDate>
		<dc:creator>Éric</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[akamai]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[cdn]]></category>
		<category><![CDATA[dns]]></category>
		<category><![CDATA[latence]]></category>
		<category><![CDATA[proxy]]></category>
		<category><![CDATA[réseau]]></category>

		<guid isPermaLink="false">http://performance.survol.fr/?p=503</guid>
		<description><![CDATA[La latence est une des composantes qui pénalise le plus les performances actuellement. Les connexions Internet françaises se font plutôt à haut débit, et même un mauvais wifi laisse finalement passer assez de trafic pour que ce soit viable. Par &#8230; <a href="http://performance.survol.fr/2009/06/latence-et-cdn/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://performance.survol.fr/2008/03/impact-de-la-latence-reseau/">La latence est une des composantes qui pénalise le plus les performances actuellement</a>. Les connexions Internet françaises se font plutôt à haut débit, et même un mauvais wifi laisse finalement passer assez de trafic pour que ce soit viable. Par contre, avec l&#8217;explosion du nombre de composants par page, la latence est probablement le facteur le plus limitant.  40 composants à 50ms de latence, c&#8217;est 2 secondes de perdues. Même en imaginant utiliser deux fils de téléchargement, c&#8217;est encore une seconde d&#8217;attente. Sur une mauvaise connexion (wifi ?) ou quand on s&#8217;adresse à un site qui n&#8217;a pas de serveur en France (ou très proche), la latence peut vite exploser.</p>
<p>Je ne parle même pas de c<a href="http://www.theinquirer.fr/2009/03/20/hadopi-un-veritable-danger-pour-le-saas.html">e que pourraient nous apporter HADOPI et LOPSI2</a> s&#8217;ils filtrent les accès côté FAI (on peut leur faire confiance pour affirmer que les débits ne bougeront pas, mais en ce qui concerne la latence&#8230;). À 120ms de latence c&#8217;est d&#8217;un coup plusieurs secondes qui partent en fumée.  En fait ce sont souvent les publicités qui ont la plus grande latence. Quand le javascript qui gère la pub est bloquant et qu&#8217;on a deux ou trois redirections HTTP, on peut facilement perdre une seconde. Si vous ne me croyez pas, regardez <a href="http://venturebeat.com/2008/09/22/is-latency-crippling-yahoos-right-media/">l&#8217;exemple de Right Media</a>.<span id="more-503"></span></p>
<h3>Les solutions</h3>
<p>Pour aller plus vite il faut donc soit avoir moins de composants par page, soit faire en sorte que la latence entre ces composants et le visiteur est réduite.  Moins de composants c&#8217;est renouveler des solutions que j&#8217;ai déjà abordé ici : mettre en cache tout ce qu&#8217;on peut, container les fichiers javascript, faire de même avec les feuilles de style, et explorer les sprites CSS pour les images.  Réduire la latence elle-même est par contre plus complexe. Comme on ne peut pas d&#8217;un coup de baguette magique améliorer la connexion du visiteur (quoi que certains tentent de <a href="http://gigaom.com/2008/08/12/fastsoft-tweaks-tcp-to-accelerate-the-internet/">jouer avec TCP</a>), il ne reste plus qu&#8217;à approcher le serveur au maximum près du fournisseur d&#8217;accès du visiteur.</p>
<p>Pour un public français c&#8217;est réalisable, les FAI français font du peering entre eux, tout est regroupé entre quelques gros, la latence due au placement géographique est probablement proche de zéro (pour un site américain, avoir des serveurs sur les deux côtes au lieu d&#8217;une seule fait une réelle différence par contre). Sauf qu&#8217;assez souvent ce n&#8217;est pas un site français c&#8217;est un site francophone, ou adressé aux français (qui sont peut être en déplacement).  Reste que même pour un site non touristique qu&#8217;on croit adresser aux français métropolitain, il y a des requêtes qui viennent des DOM TOM, des pays limitrophes, des pays européens (oui, je travaille tous les jours de Paris avec une adresse IP londonienne ) et finalement d&#8217;un peu partout dans le monde (je suis toujours étonné de voir les statistiques géographiques de ce blog).</p>
<h3>Content Delivery Network</h3>
<p>L&#8217;idéal serait donc d&#8217;avoir un serveur local chez chaque FAI. Malheureusement on se doute bien qu&#8217;au niveau coûts c&#8217;est infaisable, d&#8217;autant plus s&#8217;il faut les synchroniser. Les CDN, puisque c&#8217;est comme ça que ça s&#8217;appelle (Content Delivery Network, réseau de distribution de contenu), se placent à quelques endroits géographiques, avec des liens réseaux spécifiques vers les FAI principaux et entre les différents emplacements.  <a href="http://www.datacenterknowledge.com/archives/2008/11/18/where-amazons-data-centers-are-located/">Amazon propose donc quatorze emplacements</a>, huit aux USA, quatre en Europe (Londres, Dublin, Amsterdam et Francfort), ainsi que deux en Asie (Hong Kong et Tokyo). Akamaï, le leader, propose 71 pays différents (et probablement plusieurs emplacements aux USA).</p>
<p>Dans l&#8217;ensemble sur les CDN donnant des listes précises, les pays du nord et les USA semblent les mieux couverts mais ce peut être un biais du à mes sources d&#8217;information. N&#8217;ayant pas eu à faire de recherche spécifique  l&#8217;Asie l&#8217;Afrique ou l&#8217;Europe ont peut être quelques CDN spécifiques. À vous de fouiller dans <a href="http://www.cdnlist.com/">la cinquantaine de CDN dans le monde</a>.  Akamaï propose une petite application pour <a href="http://www.akamai.com/html/technology/dataviz2.html">constater la latence entre deux villes</a>. Bon, c&#8217;est visiblement très biaisé, mais le principe est bien là, lui.</p>
<h3>Fonctionnement</h3>
<p>Sur le principe un CDN ce n&#8217;est pas bien compliqué. Il s&#8217;agit de modifier le DNS pour faire pointer vers celui du CDN. Là on utilise des DNS personnalisés chez différents FAI, ou un système de tracking géographique des adresses IP pour renvoyer les différents utilisateurs chacun vers le serveur le plus proche de chez eux. Le serveur lui même est soit pré-rempli avec tous les composants utiles, soit fonctionne comme un proxy évolué (ce qui demande que vous même gériez correctement toutes vos entêtes de cache).</p>
<h3>Dois-je utiliser un CDN ?</h3>
<p>Pour un petit site français, pas certain. Pour un site plus gros, cela peut permettre de déporter les coûts de serveurs et de bande passante, c&#8217;est uniquement une question financière.  Par contre, dès que vous visez plus international, en dehors de la simple Europe occidentale, ça peut commencer à prendre son sens. Les coûts sont assez progressifs et abordables même pour une petite société (Akamaï part à partir de 150$/mois, Amazon a un prix au consommé qui semble ridicule pour des petits trafics).</p>
<p>Une seule chose, ne vérifiez pas l&#8217;efficacité depuis votre bureau français, avec une faible latence. Au mieux entre un CDN avec un serveur à Paris et votre propre serveur parisien, il n&#8217;y aura pas grande différence. Il se pourrait même que le CDN semble ralentir vos pages (vu qu&#8217;il faudra peut être joindre Londres pour certains réseaux). Par contre pour d&#8217;autres, aux DOM TOM ou à l&#8217;étranger, la différence sera notable. Un petit coup par <a href="http://www.webpagetest.org/">webpagetest</a> peut donner un premier aperçu si vous le souhaitez.</p>
<p>Au pire, rien ne vous empêche de fournir un lien directement vers votre serveur quand le visiteur est dans la même zone géographique, et un lien vers le CDN sinon. Une petite reconnaissance de l&#8217;adresse IP devrait suffire et le risque de dégrader les performances en cas d&#8217;erreur est assez faible.</p>
]]></content:encoded>
			<wfw:commentRss>http://performance.survol.fr/2009/06/latence-et-cdn/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Préchargement des images CSS avec Jquery</title>
		<link>http://performance.survol.fr/2009/04/prechargement-des-images-css-avec-jquery/</link>
		<comments>http://performance.survol.fr/2009/04/prechargement-des-images-css-avec-jquery/#comments</comments>
		<pubDate>Fri, 17 Apr 2009 11:00:44 +0000</pubDate>
		<dc:creator>Éric</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[image]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[préchargement]]></category>
		<category><![CDATA[prefetch]]></category>
		<category><![CDATA[réseau]]></category>

		<guid isPermaLink="false">http://performance.survol.fr/?p=477</guid>
		<description><![CDATA[Dans le préchargement l&#8217;idée est de faire travailler le navigateur avant que l&#8217;utilisateur ne demande les documents pour que ce soit quasiment instantané ensuite. On attend la fin de chargement de la page, et on lance par avance le téléchargement &#8230; <a href="http://performance.survol.fr/2009/04/prechargement-des-images-css-avec-jquery/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Dans le préchargement l&#8217;idée est de faire travailler le navigateur avant que l&#8217;utilisateur ne demande les documents pour que ce soit quasiment instantané ensuite. On attend la fin de chargement de la page, et on lance par avance le téléchargement de plusieurs liens dont on pense qu&#8217;ils serviront plus tard. C&#8217;est très intéressant pour quelques logos, css ou javascript. Imaginez une page d&#8217;accueil avec un style bien différent du reste du site : il peut être avantageux de précharger la feuille de style ou le javascript qui seront utilisés sur les autres pages.</p>
<p>C&#8217;est Marc Hertzog qui se colle à <a href="http://marcarea.com/weblog/?post/2008/07/12/Plug-in-jQuery-pour-pre-charger-les-images-CSS">l&#8217;exercice</a> avec JQuery. Il a amélioré <a href="http://www.filamentgroup.com/lab/update_automatically_preload_images_from_css_with_jquery/">un module de Scott Jehl</a> qui lit une feuille de style et tente de précharger toutes les images qui y sont référencées. L&#8217;idée est séduisante. On supprime alors les temps d&#8217;attente pour les images qui s&#8217;affichent au survol de la souris ou sur les pages suivantes.</p>
<p>L&#8217;idée est séduisante mais je n&#8217;accroche pas tout à fait.<span id="more-477"></span> Tout d&#8217;abord parce que c&#8217;est au navigateur de faire ça. J&#8217;ai souvent dit que sur les performances on compensait les manques des navigateurs et qu&#8217;il fallait être pragmatiques (le faire quand même même si dans l&#8217;idéal c&#8217;est le boulot du navigateur) mais là il s&#8217;agit de quelque chose de simple, très simple. Quand un &laquo;&nbsp;quick win&nbsp;&raquo; n&#8217;est pas réalisé par des gens intelligents &#8211; et les développeurs de navigateur le sont &#8211; c&#8217;est qu&#8217;il y a anguille sous roche.</p>
<p>Le plus gros défaut que je vois est celui inhérent à tout préchargement : on fait travailler le navigateur. Sur un poste personnel avec une navigation très linéaire ça n&#8217;a d&#8217;effet négatif quasi que sur les prestataires réseau. Mais sur une ligne partagée (entreprise, wifi), avec des gens très connectés (vidéo en streaming parallèle, deezer ou spotify en tâche de fond), ou simplement sur une navigation avec beaucoup d&#8217;onglets (vous faites une recherche, vous ouvrez beaucoup de pages en parallèle), vous pénalisez l&#8217;utilisateur ou ses voisins. Même chose pour un utilisateur en itinérance : utiliser son réseau et son processeur pour ça aura une influence forte sur sa batterie.</p>
<p>Le préchargement reste une bonne idée, mais à petite dose, pour des choses ciblées, prévues. Ici on télécharge tout sans discernement. C&#8217;est certain, on va aussi télécharger des éléments qui ont une faible probabilité d&#8217;être utile. Dans les commentaires de la version originale du script on propose de faire un tri sur l&#8217;url de chaque image, suivant son répertoire on décide si c&#8217;est une image qui doit être préchargée ou pas. On résout ainsi l&#8217;occupation réseau (mais pas l&#8217;occupation processeur), mais ça commence à faire usine à gaz. Sans compter que une même image peut avoir du sens pour un préchargement sur certaines pages mais pas sur d&#8217;autres.</p>
<p>À ce compte là autant lister les images à précharger dans un tableau javascript au lieu de lire toute la feuille de style. Ou mieux, des <a href="https://developer.mozilla.org/En/Link_prefetching_FAQ">&lt;link rel=&nbsp;&raquo;prefetch&nbsp;&raquo;&gt;</a> parce que c&#8217;est fait pour ça.</p>
<p>Enfin, c&#8217;est surtout utile pour les changement d&#8217;image au survol de la souris, ou sur une action utilisateur. Dans ce cas on modifie l&#8217;image en cours, ou on affiche des icônes. Bref, on se retrouve très généralement dans des cas où les images concernées sont de toutes façons dans des sprites, soit avec une liste d&#8217;icône, soit avec l&#8217;image qu&#8217;on remplace &#8211; l&#8217;image contient alors et la version sans survol et la version avec survol.</p>
<p>Bref, l&#8217;idée est bonne mais je reste septique sur la pertinence de mettre en place une solution générique de ce type.</p>
]]></content:encoded>
			<wfw:commentRss>http://performance.survol.fr/2009/04/prechargement-des-images-css-avec-jquery/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Cache central des bibliothèques javascript</title>
		<link>http://performance.survol.fr/2009/02/cache-central-des-bibliotheques-javascript/</link>
		<comments>http://performance.survol.fr/2009/02/cache-central-des-bibliotheques-javascript/#comments</comments>
		<pubDate>Tue, 17 Feb 2009 11:00:15 +0000</pubDate>
		<dc:creator>Éric</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[cdn]]></category>
		<category><![CDATA[dns]]></category>
		<category><![CDATA[domaine]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[latence]]></category>
		<category><![CDATA[proxy]]></category>
		<category><![CDATA[réseau]]></category>
		<category><![CDATA[url]]></category>
		<category><![CDATA[yahoo!]]></category>

		<guid isPermaLink="false">http://performance.survol.fr/?p=410</guid>
		<description><![CDATA[On m&#8217;a posé quelques fois la question alors voici la réponse : Oui. Oui il faut, quand vous le pouvez, utiliser les liens centralisés de Google ou de Yahoo pour vos bibliothèques javascript. Je parle de ne pas recopier jquery &#8230; <a href="http://performance.survol.fr/2009/02/cache-central-des-bibliotheques-javascript/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>On m&#8217;a posé quelques fois la question alors voici la réponse : Oui.</p>
<p>Oui il faut, quand vous le pouvez, utiliser <a href="http://code.google.com/apis/ajaxlibs/documentation/index.html#AjaxLibraries">les liens centralisés de Google</a> ou <a href="http://developer.yahoo.com/yui/articles/hosting/#background">de Yahoo</a> pour vos bibliothèques javascript. Je parle de ne pas recopier jquery ou yui directement sur vos serveurs, mais d&#8217;utiliser les liens centralisés proposés par les deux moteurs de recherche.</p>
<p>Voilà pour la réponse générique, ensuite on peut détailler un peu.</p>
<p><span id="more-410"></span></p>
<h3 lang="en">Content delivery network</h3>
<p>Le premier gain c&#8217;est l&#8217;utilisation des <acronym lang="en" title="content delivery network">CDN</acronym> de Yahoo! et de Google. Le principe du <a href="http://performance.survol.fr/avec/cdn/">CDN</a> c&#8217;est plus ou moins placer des serveurs dans plusieurs pays, voire directement chez les FAI, pour que le trajet fait sur le réseau soit le plus court possible. On vise une latence réduite. <a href="http://performance.survol.fr/2008/03/impact-de-la-latence-reseau/">La latence ça peut tuer un site web</a>.</p>
<p>Seuls les plus gros sites web peuvent s&#8217;offrir des CDN. Profiter de Yahoo! ou Google c&#8217;est toujours appréciable.</p>
<p>Maintenant vous n&#8217;utiliserez qu&#8217;une seule grosse bibliothèque javascript. En échange vous allez utiliser un nom de domaine supplémentaire, donc <a href="http://performance.survol.fr/2008/07/analyse-requete-http-serveur-et-reseau/">une requête DNS supplémentaire et une connexion de plus</a>. Le deal est intéressant si ce qu&#8217;on gagne en latence dépasse ce que coûte la requête DNS.</p>
<p>Soyons clairs, si vos contenus ne sont pas sur le même continent qu&#8217;une partie sensible de vos clients, alors c&#8217;est un bon deal, n&#8217;hésitez pas. Aux États-Unis, éviter de traverser de l&#8217;Alaska vers New-York, c&#8217;est du temps gagné, non négligeable. Mais en même temps les sociétés vraiment internationales ont déjà souvent un hébergement par pays ou continent, ou utilisent déjà un CDN.</p>
<p>Si vous restez en Europe occidentale ça devient déjà moins clair. Si vous êtes hébergés en France dans un gros datacenter et que vos clients sont en France &#8230; là pas sur que le bénéfice du CDN soit réel. Les FAI ont des liens de peering entre eux et avec les hébergeurs français, la latence est globalement faible dès le départ. (Note: ceci n&#8217;a pas été vérifié par des tests, je suis preneur d&#8217;avis et de retours d&#8217;expérience sur la pertinence de CDN pour un trafic français avec un hébergement en France)</p>
<h3>Nombre de domaines</h3>
<p>Le second aspect de ces caches centralisés c&#8217;est le fait qu&#8217;ils sont justement sur un domaine séparé. Il y a du pour et du contre.</p>
<p>Dans le pour, votre Javascript peut être téléchargé immédiatement même si <a href="http://performance.survol.fr/2008/04/limitation-du-nombre-de-requetes/">les files de téléchargement</a> sont déjà occupées avec d&#8217;autres éléments de votre site. Maintenant comme on définit souvent ce genre de bibliothèques javascript tout en haut de page, les files de téléchargement sont généralement vides à ce moment là de toutes façons. Bref, je ne suis pas convaincu.</p>
<p>Toujours dans le pour, <a href="http://performance.survol.fr/2008/12/quel-avenir/">si votre navigateur est très récent (comprendre&nbsp;: IE 8, Safari 4, Firefox 3.1) le javascript ne bloque pas les autres téléchargements</a>. Là aussi, avoir un domaine différent évite d&#8217;utiliser un slot dans vos autres téléchargements. En pratique, avec six slots simultanés minimum sur ces navigateurs, je ne suis pas convaincu que cela fasse une différence fondamentale.</p>
<p>Bref, pas convaincu, sachant qu&#8217;il y a du contre qui s&#8217;ajoute : avec un nom de domaine en plus, comme on l&#8217;a vu, il y a une requête DNS supplémentaire. Est-ce que ça vaut le coup pour un unique fichier ? pas sûr du tout.</p>
<h3>Cache centralisé</h3>
<p>Troisième aspect, en utilisant les liens de Google et Yahoo! on finit par tous utiliser les mêmes URL pour nos bibliothèques javascript.</p>
<p>Le résultat c&#8217;est que pour les bibliothèques les plus populaires, cela augmente la probabilité que vous l&#8217;ayez déjà en <a href="http://performance.survol.fr/2008/10/expires-et-cache-control-une-date-limite-de-consommation-pour-vos-contenus/">cache</a> à cause d&#8217;un site précédent. Là le gain est important, surtout pour vos pages d&#8217;accueil (celles qui ont le plus gros trafic &laquo;&nbsp;cache vide&nbsp;&raquo;). Reste qu&#8217;en réalité l&#8217;URL contient la version de la bibliothèque et tous les sites n&#8217;utilisent pas les mêmes versions, ou même les mêmes bibliothèques. La mutualisation est assez limitée et le gain reste à prouver.</p>
<p>L&#8217;avantage concret est par contre visible pour les entreprises et pour les universités. Ces dernières ont des proxys cache qui auront toutes les chance d&#8217;avoir déjà votre bibliothèque en cache, dans la bonne version. Sur la cinquantaine (ou le millier) de collègues, il y en aura bien un qui aura téléchargé la bibliothèque avant vous.</p>
<p>La question est donc, vos visiteurs sont-ils sur des lignes professionnelles ou des lignes de particuliers ? dans ce second cas le gain n&#8217;est pas évident.</p>
<h3>Mais alors, pourquoi répondre &laquo;&nbsp;oui&nbsp;&raquo; ?</h3>
<p>Parce que je parlais jusqu&#8217;à maintenant du cas idéal. Si vous avez déjà un CDN, que vos ressources statiques sont déjà sur domaine séparé, et que vos entêtes de cache sont bien réglées, alors gardez vos bibliothèques chez vous. Mais &#8230; ce n&#8217;était le cas pour aucun de ceux qui m&#8217;ont posé la question.</p>
<p>En fait je doute que ce soit le cas pour quiconque se pose la question. Ceux qui ont déjà fait tout le chemin de performance avec CDN, domaine tiers et entêtes de cache, ils ont souvent les moyens de tester eux même quelle est la meilleure solution. Ou mieux, ils ont déjà réalisé que pour éliminer une requête HTTP il faut déjà fusionner leur bibliothèque javascript avec leur code javascript spécifique. Bref, la question est sans objet pour eux.</p>
<p>Pour les autres, qui n&#8217;ont pas les moyens d&#8217;utiliser un CDN quand bien même ils en auraient besoin, ou qui n&#8217;ont pas déjà un domaine séparé pour les ressources statiques, ou qui ne gèrent pas correctement leurs entêtes de cache, pour eux c&#8217;est intéressant. Ce n&#8217;est pas parfait, mais c&#8217;est un mieux, une démarche d&#8217;amélioration progressive. Pour vous, qui vous posez la question, la réponse est probablement &laquo;&nbsp;oui, utilisez les liens de Yahoo et Google pour vos bibliothèques javascript&nbsp;&raquo;. Et puis &#8230; ça fait autant de bande passante en moins à payer.</p>
<p>En cas de doute, le &laquo;&nbsp;oui&nbsp;&raquo; a plus de chance d&#8217;être positif ou sans effet que de réellement être négatif.</p>
]]></content:encoded>
			<wfw:commentRss>http://performance.survol.fr/2009/02/cache-central-des-bibliotheques-javascript/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Quelques outils en ligne</title>
		<link>http://performance.survol.fr/2008/12/quelques-outils-en-ligne/</link>
		<comments>http://performance.survol.fr/2008/12/quelques-outils-en-ligne/#comments</comments>
		<pubDate>Wed, 17 Dec 2008 11:00:53 +0000</pubDate>
		<dc:creator>Éric</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[analyse]]></category>
		<category><![CDATA[cascade]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[outils]]></category>
		<category><![CDATA[réseau]]></category>

		<guid isPermaLink="false">http://performance.survol.fr/?p=341</guid>
		<description><![CDATA[Je vous avais présenté quelques outils, aujourd&#8217;hui en voilà trois autres, en ligne. Le concept de ces outils est le même : on prend une URL, on lance la page, et on trace la cascade des requêtes HTTP avec quelques &#8230; <a href="http://performance.survol.fr/2008/12/quelques-outils-en-ligne/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Je vous avais <a href="http://performance.survol.fr/avec/outils/">présenté quelques outils</a>, aujourd&#8217;hui en voilà trois autres, en ligne.</p>
<p>Le concept de ces outils est le même : on prend une URL, on lance la page, et on trace la cascade des requêtes HTTP avec quelques statistiques. C&#8217;est là qu&#8217;on voit le temps pris par chaque composant, par la somme des composants, et les éventuels problèmes de performance comme les scripts bloquants.<span id="more-341"></span></p>
<h3>Pingdom : simple et clair</h3>
<p>Le plus simple, et peut être le plus joli, c&#8217;est <a href="http://tools.pingdom.com/">Pingdom</a>. Il se contente de tracer la cascade, en précisant les temps de connexion TCP, d&#8217;envoi et de réception, ainsi que les poids des divers composants. Il n&#8217;y a pas de paramétrage, et il semble que le moteur se permette de lancer presque 10 connexions simultanées. Bref, n&#8217;en faites pas des analyses trop poussées. Par contre pour montrer l&#8217;aperçu de la cascade ou un problème significatif au détour d&#8217;une conversation, c&#8217;est clairement un des outils à retenir. L&#8217;interface est en effet suffisamment jolie pour attirer le non-spécialiste.</p>
<p style="text-align: center;"><a href="http://performance.survol.fr/wp-content/uploads/2008/12/picture-3.png"><img class="size-medium wp-image-342 aligncenter" title="Pingdom" src="http://performance.survol.fr/wp-content/uploads/2008/12/picture-3-300x190.png" alt="" width="300" height="190" /></a></p>
<h3>Site-perf : paramétrable jusqu&#8217;au bout</h3>
<p>Le deuxième outil en ligne est <a href="http://site-perf.com/">site-perf</a>. Le site se veut regrouper des informations sur la performance des sites web, mais c&#8217;est surtout pour son test de performance en ligne qu&#8217;il est intéressant. Il offre plusieurs sources géographiques pour lancer le test et un paramétrage complet : nombre de connexions simultanées, bande passante, latence, qualité de la ligne (% de perte de paquets), compression, keep-alive, login, adresse IP&#8230; tout y est. Je n&#8217;ai pas fait suffisamment de test pour m&#8217;assurer que le résultat est précis ou cohérent avec les outils &laquo;&nbsp;de confiance&nbsp;&raquo; comme <a href="http://www.alphaworks.ibm.com/tech/pagedetailer">IBM Page Detailer</a>, mais le résultat est sans appel : une cascade précise avec six états, dont le temps de résolution DNS, le détail des informations de cache HTTP, et un résumé cohérent.</p>
<p>Les deux seuls défauts sont la largeur de la cascade, qui mériterait de pouvoir prendre plus de place pour une meilleure lecture, et le manque d&#8217;un résumé par type de composant (combien m&#8217;ont coûté les images au total ?).</p>
<p><a href="http://performance.survol.fr/wp-content/uploads/2008/12/picture-4.png"><img class="aligncenter size-medium wp-image-343" title="Site-Perf" src="http://performance.survol.fr/wp-content/uploads/2008/12/picture-4-300x187.png" alt="" width="300" height="187" /></a></p>
<h3>Web Page Test : aussi complet que la version bureau</h3>
<p>Le dernier outil c&#8217;est <a href="http://performance.webpagetest.org:8080/">webpagetest</a>, la version en ligne de <a href="http://pagetest.wiki.sourceforge.net/">AOL Page Test</a>. La cascade est précise et on peut avoir confiance dans l&#8217;outil si c&#8217;est juste une automatisation de la version bureau du logiciel. Moins joli que pingdom (en fait même carrément moche), webpagetest est aussi légèrement moins paramétrable que site-perf.</p>
<p>On a accès à trois sources géographiques avec leurs spécificités, et un choix du nombre de requêtes simultanées. Pour rattraper le tout il est possible de scripter le test. On peut aller réaliser un parcours sur le site, envoyer un formulaire ou accéder une page protégée par authentification. Il manque malheureusement la possibilité de modifier finement la bande passante ou de modifier la latence artificiellement. Vu l&#8217;importance de la latence dans les tests, c&#8217;est dommage.</p>
<p><a href="http://performance.survol.fr/wp-content/uploads/2008/12/picture-5.png"><img class="aligncenter size-medium wp-image-344" title="Paramétrage webpagetest" src="http://performance.survol.fr/wp-content/uploads/2008/12/picture-5-300x271.png" alt="" width="300" height="271" /></a></p>
<p>L&#8217;intérêt de webpagetest c&#8217;est surtout le résultat. On y retrouve une cascade précise et très claire (en grande largeur), qui comprend aussi les temps de début de rendu et de fin de rendu de la page : indispensable si on veut jouer sur le ressenti utilisateur et pas uniquement sur les chiffres bruts.  Derrière cette cascade on a un résumé ressource par ressource des différents temps et poids, avec toutes les entêtes HTTP. Bref, tout ce qui est nécessaire pour travailler. Il y a même un tableau avec des recommandations pour vérifier des critères comme le cache, gzip, la concaténation css/js, le keep-alive, la minimisation ou le keep-alive.</p>
<p>Le double effet kisskool de webpagetest c&#8217;est que ces informations sont fournies en double : une fois pour le premier accès avec un cache vide, et une seconde fois, pour simuler un cache correctement initialisé. Indispensable là aussi. Mieux, cascade et résumés sont disponibles sous forme d&#8217;image et peuvent donc facilement être sauvegardés pour un rapport ou pour comparaison entre deux dates.</p>
<p><a href="http://performance.survol.fr/wp-content/uploads/2008/12/picture-61.png"><img class="aligncenter size-medium wp-image-346" title="Résultat webpagetest" src="http://performance.survol.fr/wp-content/uploads/2008/12/picture-61-300x205.png" alt="" width="300" height="205" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://performance.survol.fr/2008/12/quelques-outils-en-ligne/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Analyse d&#8217;une requête HTTP &#8211; serveur et réseau</title>
		<link>http://performance.survol.fr/2008/07/analyse-requete-http-serveur-et-reseau/</link>
		<comments>http://performance.survol.fr/2008/07/analyse-requete-http-serveur-et-reseau/#comments</comments>
		<pubDate>Wed, 23 Jul 2008 10:00:02 +0000</pubDate>
		<dc:creator>Éric</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[compression]]></category>
		<category><![CDATA[cookie]]></category>
		<category><![CDATA[dns]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[minimisation]]></category>
		<category><![CDATA[pipelining]]></category>
		<category><![CDATA[réseau]]></category>
		<category><![CDATA[schéma]]></category>
		<category><![CDATA[serveur]]></category>
		<category><![CDATA[sprite]]></category>
		<category><![CDATA[tampon]]></category>

		<guid isPermaLink="false">http://performance.survol.fr/?p=55</guid>
		<description><![CDATA[On parle de temps, de performance, mais finalement que mesure t-on ? La question n&#8217;est pas inutile puisque pour une même requête il y a bien trois étape visibles du point de vue du visiteur, cinq du point de vue &#8230; <a href="http://performance.survol.fr/2008/07/analyse-requete-http-serveur-et-reseau/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>On parle de temps, de performance, mais finalement que mesure t-on ? La question n&#8217;est pas inutile puisque pour une même requête il y a bien trois étape visibles du point de vue du visiteur, cinq du point de vue du navigateur et autant pour le serveur. Alors, que mesure t-on ?</p>
<p><span id="more-52"></span>Je vous propose un petit schéma incomplet des interactions lors de la requête d&#8217;une page HTML (attention, aucune échelle ou proportion n&#8217;est respectée).</p>
<p><a style="text-decoration: none;" href="http://performance.survol.fr/wp-content/uploads/2008/07/http-big.png"><img class="alignnone size-full wp-image-59" title="Analyse d\'une requête HTTP" src="http://performance.survol.fr/wp-content/uploads/2008/07/http-little.png" alt="" /></a></p>
<p>Alors, vous mesurez quoi ?</p>
<p><strong>La requête DNS</strong></p>
<p>Une fois que le visiteur clique sur un lien, c&#8217;est une requête DNS qui est lancée par le navigateur et environ 30ms qui sont perdues, parfois même jusqu&#8217;à 100 ou 150ms (triangle gris sur le schéma). Microsoft Internet Explorer 6 cache cette information pendant 30 minutes mais les autres navigateurs la relancent plus souvent. Mozilla Firefox ne garde le résultat de la requête DNS que pour une petite minute. Vous l&#8217;aurez donc quasiment à chaque nouvelle page. Vous pouvez réduire l&#8217;influence des requêtes DNS en limitant le nombre de domaines et sous-domaines utilisés par votre site. <strong>Gardez le nombre de domaines en dessous de quatre</strong>.</p>
<h3>La connexion au serveur</h3>
<p>L&#8217;étape suivante c&#8217;est l&#8217;établissement de la connexion avec le serveur que vous souhaitez joindre (triangle vers sur le schéma). C&#8217;est assez rapide mais ça reste quelque chose qui va impacter les performances. <strong>Autorisez le keep-alive pour les ressources statiques</strong> (images, feuilles de styles, javascript) : Le navigateur et le serveur vont réutiliser la connexion existante au lieu de rétablir une nouvelle connexion pour chaque composant. Le gain est notable, j&#8217;en avais <a href="http://performance.survol.fr/2008/04/keep-alive-et-connexions-persistantes/">déja parlé</a>.</p>
<p>Maintenant le keep-alive c&#8217;est aussi ce qui va garder la connexion ouverte inutilement une fois que vous aurez téléchargé tous les composants. C&#8217;est le rectangle vert en bas sur le schéma. C&#8217;est coûteux pour vs serveurs. Désactivez donc le keep-alive sur le serveur qui renvoie les pages HTML, et réduisez la valeur pour les autres : cinq secondes sont bien suffisantes.</p>
<h3>La requête HTTP elle-même, et l&#8217;attente qui suit</h3>
<p>Vient ensuite la requête HTTP elle-même (parallélogramme jaune sur le schéma). Vous voyez qu&#8217;elle prend un certain temps, symbolisée par une épaisseur sur le schéma. En cumulant toutes les entêtes et un cookie classique, votre requête peut facilement prendre 1ko. Pensez donc à <strong>réduire la taille du cookie</strong>, et même à <strong>ne pas avoir de cookie pour les ressources statiques</strong> en les mettant sur un domaine tiers.</p>
<p>Par la suite, pour réduire l&#8217;influence des requêtes HTTP, il ne reste plus qu&#8217;à en faire moins. En fait c&#8217;est assez simple. Il suffit d&#8217;<strong>aggréger plusieurs fichiers en un seul</strong>, qu&#8217;on parle de <a href="http://performance.survol.fr/2008/03/strategies-doptimisation-du-cache/">CSS et javascript</a>, ou de <a href="http://performance.survol.fr/2008/06/des-sprites-jusqua-plus-soif/">sprites pour les images</a>. Vous épargnez le temps de faire la requête, mais aussi tout le temps d&#8217;attente du navigateur entre la fin de la requête et la réception de la réponse (espace blanc entre les parallélogrammes bleus et jaunes sur la ligne de temps du navigateur).</p>
<p>Une autre possibilité c&#8217;est d&#8217;envoyer plusieurs requêtes HTTP coup sur coup sans attendre les réponses. On utilise alors au mieux cet espace inutile entre la fin de la requête et le début de la réponse. On se permet même d&#8217;envoyer des donner dans un sens pendant qu&#8217;on en reçoit de l&#8217;autre côté, donc superposer des requêtes jaunes dans mon schéma avec des réponses bleues. C&#8217;est ce qui est réalisé avec le <a href="http://performance.survol.fr/2008/04/pipelining-enchainer-les-requetes-http/">pipelining HTTP</a>.</p>
<h3>Le calcul de la page par le serveur</h3>
<p>Voilà la mesure du diable. Dès qu&#8217;on parle de performance tout le monde va vite mesurer ce temps de génération des pages, en mauve sur le schéma. Même si l&#8217;échelle et les proportions ne sont pas respectées sur le schéma, il est évident que cette mesure n&#8217;est vraiment pas la a seule, ni même la plus importante. Pour des pages bien faites et des serveurs qui ne sont pas surchargées, il est très rare d&#8217;avoir des pages qui prennent plus de 100ms pour le calcul serveur. C&#8217;est généralement dix fois moins, alors que le chargement complet de la page pour le visiteur prend lui plusieurs secondes.</p>
<p>Mais surtout, c&#8217;est létape qui est souvent la première à être optimisée, et celle où il est assez complexe de gagner encore des performances si on a déjà penser au cache. <strong>Ne vous focalisez pas sur le temps de génération des pages</strong>, sauf s&#8217;il est flagrant qu&#8217;il est disproportionné par rapport aux besoins.</p>
<p>Éventuellement, si votre page peut mettre longtemps à se générer et que c&#8217;est facile à faire, vous pouvez <strong>forcer un vidage du tampon au milieu de la génération de la page</strong>, pour que l&#8217;utilisateur commence à voir le contenu réel de la page et télécharge les composants tiers pendant que le calcul de la page continue à se faire. L&#8217;équipe <a href="http://developer.yahoo.com/performance/rules.html#flush">Performance de Yahoo! en parle</a>, l&#8217;équipe Search aurait eu de bons résultats avec cette technique.</p>
<h3>Le téléchargement de la page</h3>
<p>La dernière étape du point de vue du serveur c&#8217;est le téléchargement de la page elle-même. C&#8217;est un des postes qui impactent le plus les performances. On a beau faire des publicités pour des liaisons à 24mb/s, si vous téléchargez une pages HTML à 2mb/s c&#8217;est bien. Et derrière si on compte les images, les cookies, les javascript, les feuilles de style, le flash, les vidéo, et la page HTML elle-même, ça prend du temps, incompressible.</p>
<p>Enfin certaines choses sont incompressibles, d&#8217;autres justement&#8230; vous pouver <a href="http://performance.survol.fr/2008/04/minimiser-le-javascript/">minimiser les javascript et CSS</a>, mais aussi <a href="http://performance.survol.fr/2008/04/compression-avant-transfert/">utiliser la compression HTTP</a> pour tout ce qui est fichier texte (HTML, javascript, CSS, XML, Json, etc.). Les résultats sont spectaculaires et il est facile de diviser le poids par dix, donc le temps de téléchargement d&#8217;autant.</p>
<p>On peut aussi faire bien mieux, et réduire tout le téléchargement de la page à quelques octets. Il s&#8217;agit simplement de repérer quand le navigateur a déjà une page similaire en cache, et de lui répondre un code HTTP 304 &laquo;&nbsp;la page n&#8217;a pas changée&nbsp;&raquo;. Ca fonctionne à base d&#8217;<a href="http://performance.survol.fr/2008/06/desactiver-les-etags/">ETag</a>, de date de modification et de requête conditionnelle HTTP. </p>
<h3>Et entre le visiteur et son navigateur ?</h3>
<p>Je n&#8217;ai parlé que de la partie basse du schéma, en oubliant tout ce qu&#8217;il se passe entre le navigateur et l&#8217;humain derrière son écran. Ca a l&#8217;air plus simple parce qu&#8217;il y a moins de composants en jeu, mais c&#8217;est là que se passe une bonne partie des problèmes de performance, et pas forcément les plus simples à gérer.</p>
<p>On en parlera dans un prochain billet, vous voulez bien ?</p>
<p>En attendant retenez : </p>
<ul>
<li>Le début du rendu du navigateur ne correspond pas avec le début de la réception de la page HTML.</li>
<li>La fin l&#8217;interprétation du HTML ne correspond pas du tout avec la fin de la réception de la page HTML.</li>
<li>La fin du rendu total de la page peut intervenir plusieurs secondes après la fin de la réception de la page HTML.</li>
</ul>
<p>Mais de toutes façons le jeu c&#8217;est le plus possible d&#8217;éviter tout le schéma en lui même : réduire le nombre de requêtes HTTP, soit par une réduction du nombre de composants, soit par une exploitation au mieux du cache.</p>
]]></content:encoded>
			<wfw:commentRss>http://performance.survol.fr/2008/07/analyse-requete-http-serveur-et-reseau/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Désactiver les ETags ?</title>
		<link>http://performance.survol.fr/2008/06/desactiver-les-etags/</link>
		<comments>http://performance.survol.fr/2008/06/desactiver-les-etags/#comments</comments>
		<pubDate>Wed, 11 Jun 2008 10:00:19 +0000</pubDate>
		<dc:creator>Éric</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[etag]]></category>
		<category><![CDATA[réseau]]></category>

		<guid isPermaLink="false">http://performance.survol.fr/?p=44</guid>
		<description><![CDATA[Après un test de votre site sur Yslow vous retrouvez une recommandation qui vous propose de désactiver les ETags. Une recherche rapide vous mène sur les pages de l&#8217;équipe performance de Yahoo! qui vous disent la même chose. Qu&#8217;est ce &#8230; <a href="http://performance.survol.fr/2008/06/desactiver-les-etags/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Après un test de votre site sur Yslow vous retrouvez une recommandation qui vous propose de désactiver les ETags. Une recherche rapide vous mène sur les pages de l&#8217;équipe performance de Yahoo! qui vous disent la même chose.</p>
<h3>Qu&#8217;est ce qu&#8217;un ETag ?</h3>
<p>Un ETag sert au serveur web à identifier une ressource et sa version. La valeur d&#8217;un ETag est libre, la seule contrainte est que l&#8217;ETag soit unique pour une URL donnée. Deux versions d&#8217;un même document auront donc deux ETags différents ; dans le temps la valeur d&#8217;un ETag ne devrait pas changer si le document lui même n&#8217;évolue pas. <span id="more-39"></span>Cet ETag est renvoyé par défaut à chaque fois que le serveur web renvoie un contenu. On obtient donc quelque chose comme suit dans les entêtes d&#8217;une réponse HTTP 1.1 :</p>
<pre>HTTP/1.1 200 OK
Date: Sun, 08 Jun 2008 13:53:40 GMT
Last-Modified: Mon, 04 May 2008 19:43:54 GMT
<a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19">Etag</a>: "3a4ea77d-baa-f3a45280"</pre>
<p>Le navigateur s&#8217;en sert pour identifier les versions des documents qu&#8217;il met en cache. Quand on lui demandera de nouveau la même ressource, il fournira cet identifiant dans une entête de la requête HTTP. On parle alors d&#8217;une requête conditionnelle.</p>
<pre>GET /test.html HTTP/1.1
Host: www.example.org
If-Modified-Since: Mon, 05 May 2008 19:43:54 GMT
<a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26">If-None-Match</a>: "3a4ea77d-baa-f3a45280"</pre>
<p>Le serveur compare l&#8217;ETag reçu par le navigateur avec celui de la version actuelle du document demandé. Si les deux ne correspondent pas c&#8217;est que le document a été modifié depuis le dernier accès et on le renvoie normalement. Si les deux sont identique alors le serveur web peut utiliser le code de retour <code>304</code> et demander au navigateur d&#8217;utiliser sa copie en cache. On évite alors de télécharger de nouveau le document, inutilement. C&#8217;est intéressant autant pour le serveur que pour le client :</p>
<pre>HTTP/1.1 304 Not Modified
Etag: "3a4ea77d-baa-f3a45280"</pre>
<h3>D&#8217;autres détails (presque) inutiles</h3>
<p>En réalité c&#8217;est même un peu plus complet que cela puisque le navigateur peut retenir plusieurs versions du même document dans son cache et les renvoie toutes, séparées par des virgules. De son côté le serveur peut aussi avoir plusieurs formats pour un même document. Il va donc comparer toutes les dernières versions avec les identifiants proposés par le navigateur, et retourner un 304 pour la première qui correspond, en spécifiant bien pour que ETag il renvoie ce statut.</p>
<p>On peut aller plus loin en utilisant des <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3.3">identifiants dits forts et des identifiants dits faibles</a>. Ces derniers sont préfixés par <code>W/</code> et ne peuvent être utilisés que pour des requêtes GET et HEAD. Un identifiant faible est un identifiant qui peut correspondre à plusieurs représentations différentes d&#8217;un même document, ou à plusieurs versions d&#8217;une même représentation.</p>
<p>On trouve même la possibilité pour le navigateur d&#8217;utiliser un <code>If-None-Match:*</code>, qui ne va effectuer la requête que si la ressource ciblée n&#8217;existe pas encore. Soit que la représentation adaptée à cette requête particulière n&#8217;existe pas (version du navigateur par exemple), soit quelle n&#8217;a pas encore été générée et est générée à la demande.</p>
<p>Sur des requêtes de type POST ou PUT (en fait sur tout sauf GET et HEAD), la réponse n&#8217;est pas 304 (not modified) mais 412 (precondition failed). Sur un PUT le <code>If-None-Match:*</code> peut d&#8217;ailleurs gérer les problématiques de concurrence d&#8217;accès : la requête ne sera effectuée que la première fois, par la suite la ressource sera déjà crée et un statut 412 sera renvoyé.</p>
<h3>Les problèmes d&#8217;ETag</h3>
<p>En soit ce fonctionnement ne pose aucun problème. Il est supporté par l&#8217;essentiel des navigateurs et des serveurs. Quand un des intervenants ne connait pas les ETags ils sont ignorés et c&#8217;est le comportement <code>Last-Modified</code> / <code>If-Modified-Since</code> qui prend la main.</p>
<p>Il n&#8217;y a que deux problèmes potentiels : deux versions d&#8217;une même ressource avec le même ETag, ou deux ETags différents pour une même version d&#8217;une ressource. Dans le premier cas le navigateur risque de réutiliser son cache alors qu&#8217;il existe une mise à jour. Dans le second cas, celui qui nous préoccupe, le navigateur risque de re-télécharger un document qu&#8217;il a déjà en cache.</p>
<p>C&#8217;est ce dernier cas qui arrive parfois sur certains sites, et qui impacte les performances à cause de la bande passante utilisée inutilement. Cela arrive dès qu&#8217;il y a plusieurs serveurs derrière un même site web. Apache utilise par défaut un identifiant basé sur la date de dernière modification et l&#8217;inode du fichier. L&#8217;inode est garantit comme unique pour un même système de fichier.</p>
<p>S&#8217;il y a plusieurs serveurs, chacun a son propre système de fichier. L&#8217;inode sera différent sur chaque serveur, et le client risque de recevoir des ETag différents pour la même ressources. Pour peu que la requête du navigateur ne soit pas toujours gérée par le même serveur, tout le système de cache basé sur l&#8217;ETag sera mis en échec.</p>
<p>Sur certaines <a href="http://trac.lighttpd.net/trac/ticket/1279">anciennes versions de lighttpd</a>, des serveurs 32bits et des serveurs 64bits peuvent aussi donner des ETags différents bien que l&#8217;inode n&#8217;intervienne pas dans le calcul. </p>
<h3>Désactiver les ETags</h3>
<p><a href="http://developer.yahoo.net/blog/archives/2007/07/high_performanc_11.html">Conclusion simple et rapide</a> de l&#8217;équipe performance de Yahoo! : désactiver les Etags. En l&#8217;absence des ETags c&#8217;est en effet le mécanisme habituel de date de modification qui est utilisé pour générer les 304 et les caches. Ce système n&#8217;est pas parfait mais pour des ressources qui ne sont pas amenées à changer plusieurs fois par seconde il n&#8217;amène aucun problème.</p>
<p>En suivant les recommandations habituelles on ne modifie justement presque jamais une ressource statique, on créé la nouvelle version avec une nouvelle URL et on laisse l&#8217;ancienne telle quelle. Les ressources dynamiques, elles, à cause des personnalisations et des mises à jours très fréquentes, n&#8217;utilisent de toutes façons que rarement les 304 et ces systèmes de validation de cache. Quand elles le font c&#8217;est que les mises à jour ne sont pas trop fréquentes ; la limitation imposées par la résolution à la seconde des dates de modification n&#8217;est alors pas gênante.</p>
<p>Bref, on ne perd pas grand chose et on évite des problèmes dont on sait qu&#8217;ils vont survenir.</p>
<p><a href="http://httpd.apache.org/docs/2.2/mod/core.html#fileetag">Sous Apache</a> c&#8217;est fait avec <code>FileETag none</code>. Pour Microsoft IIS il y a <a href="http://support.microsoft.com/?id=922733">toute une procédure</a>.</p>
<h3>Réactiver les ETags ?</h3>
<p>Déjà, tant que vous avez un seul serveur derrière votre site web, n&#8217;hésitez pas : activez les ETags même si Yslow vous dit le contraire. Vous avez tout à y gagner et rien à y perdre.</p>
<p>Ensuite, activer tout de même les ETags n&#8217;est pas forcément une mauvaise idée. Le problème n&#8217;est pas sur la fonctionnalité elle-même, mais juste sur la façon par défaut pour Apache et IIS de générer ces identifiants. Bref, en général un cumul entre la date de modification et la taille du fichier suffit. Dans ce cas vous pouvez demander à Apache d&#8217;utiliser F<code>ileETag MTime Size</code>.</p>
<p>Enfin, ne changez pas et ne supprimez pas le calcul des ETags sur les sites qui utilisent DAV via le mod_dav_fs. Ce dernier risque de ne plus fonctionner de manière optimale.</p>
]]></content:encoded>
			<wfw:commentRss>http://performance.survol.fr/2008/06/desactiver-les-etags/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Limitations du cache Safari</title>
		<link>http://performance.survol.fr/2008/05/limitations-du-cache-webkit/</link>
		<comments>http://performance.survol.fr/2008/05/limitations-du-cache-webkit/#comments</comments>
		<pubDate>Tue, 06 May 2008 10:41:45 +0000</pubDate>
		<dc:creator>Éric</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[réseau]]></category>
		<category><![CDATA[safari]]></category>
		<category><![CDATA[webkit]]></category>

		<guid isPermaLink="false">http://performance.survol.fr/?p=30</guid>
		<description><![CDATA[Pour l&#8217;iphone Safari a de sérieuses limitations sur le cache. Yahoo! avait déjà débusqué les limites de la version iphone : les fichiers ne doivent pas dépasser 25 ko une fois décompressés et le total doit être strictement inférieur à &#8230; <a href="http://performance.survol.fr/2008/05/limitations-du-cache-webkit/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h3>Pour l&#8217;iphone</h3>
<p>Safari a de sérieuses limitations sur le cache. <a href="http://yuiblog.com/blog/2008/02/06/iphone-cacheability/">Yahoo! avait déjà débusqué les limites de la version iphone</a> : les fichiers ne doivent pas dépasser 25 ko une fois décompressés et le total doit être strictement inférieur à 500 ko. Ces limitations semblent raisonnables pour un téléphone mais ce téléphone navigue souvent sur des sites classiques, avec une bande passante très réduite. Des objets de plus de 25 ko on en trouve malheureusement fréquemment, par exemple une grosse feuille de style. Bref, minifiez vos fichiers javascript et CSS, compressez vos images.<span id="more-25"></span></p>
<p>Vous trouverez aussi des sites vous parlant d&#8217;<a href="http://www.niallkennedy.com/blog/2008/02/iphone-cache-performance.html">une limitation à 19 fichiers</a> en cache sur l&#8217;iphone, mais j&#8217;ai clairement l&#8217;impression qu&#8217;il s&#8217;agit d&#8217;une mauvaise compréhension des premiers résultats. 19 c&#8217;est le nombre maximum de fichiers de 25 ko qu&#8217;on peut faire tenir dans moins de 500 ko (donc dans 499 ko). Si vos fichiers sont plus petits je m&#8217;attends à ce qu&#8217;il puisse y en avoir plus que ça en cache, mais je n&#8217;ai pas d&#8217;iphone pour tester.</p>
<h3>Pour Safari 3</h3>
<p>Là où c&#8217;est plus étonnant c&#8217;est que <a href="http://blogs.smugmug.com/don/2008/04/04/nasty-bug-safari-doesnt-cache-stuff/">Safari 3 a lui aussi des limitations qu&#8217;on n&#8217;attendait pas</a>. En particulier les objets supérieur à 104 ko (le double si vous avez plus de 1 Go de RAM) ne sont pas mis en cache. Contrairement aux 25 ko de l&#8217;iphone, on ne sera pas vraiment limité sur les <acronym title="cascading style sheet">CSS</acronym> et le <acronym title="javascript">JS</acronym>. Par contre il nous reste des gros fichiers qu&#8217;on aimerait en cache : principalement les grosses images et les animations flash. Et ce sont justement ces fichiers qui devraient être prioritaires dans le cache. Hors de question de recharger la grosse animation flash à chaque passage. Bref, la limitation est gênante.</p>
<p>Il y a tout lieu de penser que ce sera corrigé à l&#8217;avenir, en tout cas <a href="https://bugs.webkit.org/show_bug.cgi?id=15798">un bug a été soumis en ce sens</a>. Visiblement le problème vient d&#8217;un framework qui gère la couche HTTP et pas de Safari/WebKit. Si quelqu&#8217;un est motivé, je suis curieux de savoir si la version Windows de Safari 3 ou les navigateurs webkit Linux souffrent du même problème.</p>
]]></content:encoded>
			<wfw:commentRss>http://performance.survol.fr/2008/05/limitations-du-cache-webkit/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Pages d&#8217;erreur</title>
		<link>http://performance.survol.fr/2008/04/pages-d-erreur/</link>
		<comments>http://performance.survol.fr/2008/04/pages-d-erreur/#comments</comments>
		<pubDate>Tue, 22 Apr 2008 10:00:56 +0000</pubDate>
		<dc:creator>Éric</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[404]]></category>
		<category><![CDATA[500]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[erreur]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[réseau]]></category>

		<guid isPermaLink="false">http://performance.survol.fr/?p=22</guid>
		<description><![CDATA[Rappelez-vous : cool URIs don&#8217;t change (les URIs sympa ne changent pas), et mieux, autant que possible elle ne disparaissent pas non plus. Reste que beaucoup d&#8217;éditeurs ne tiennent pas compte de cette recommandation, et que les développeurs ne peuvent s&#8217;abstenir &#8230; <a href="http://performance.survol.fr/2008/04/pages-d-erreur/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Rappelez-vous : <a lang="en" href="http://www.w3.org/Provider/Style/URI">cool URIs don&#8217;t change</a> (les URIs sympa ne changent pas), et mieux, autant que possible elle ne disparaissent pas non plus. Reste que beaucoup d&#8217;éditeurs ne tiennent pas compte de cette recommandation, et que les développeurs ne peuvent s&#8217;abstenir de faire des erreurs quand ils font des liens. </p>
<p>Ces pages d&#8217;erreurs donnent une piètre expérience à l&#8217;utilisateur, je ne l&#8217;apprend à personne. Je me concentre ici sur l&#8217;aspect performance mais sur cet aspect aussi il y a des conséquences.<span id="more-20"></span></p>
<h3>Les URIs sympa ne changent pas</h3>
<p>C&#8217;est toujours bon d&#8217;insister : les URIs sympa ne changent pas, et ne disparaissent pas. La solution unique et permanente à tous les problèmes d&#8217;erreurs est de ne pas en faire. Les erreurs 404 sont très souvent la faute des développeurs ou des éditeurs du site où elles arrivent :</p>
<p><strong>Ne cassez pas les liens</strong>, qu&#8217;ils soient internes ou en provenance de l&#8217;extérieur. Laissez vos contenus à leur adresse actuelle, quitte à ne plus les lier nulle part et qu&#8217;ils soient là juste en archive au cas où. C&#8217;est simple à dire mais c&#8217;est aussi la règle la plus importante.</p>
<p>Pour vous y aider n&#8217;hésitez pas à jeter un oeil régulier à vos journaux d&#8217;accès pour repérer les 404 et les pages référantes à fixer. Faites aussi tourner des robots sur vos pages pour détecter les liens morts. Des outils comme les outils webmaster de Google peuvent vous y aider. Ils vous montreront tous les liens morts internes et externes que fait votre site.</p>
<h3>Les page d&#8217;aide ou page d&#8217;erreur ?</h3>
<p>Quand votre serveur renvoie une erreur, il retourne souvent une page complète. C&#8217;est le cas par exemple pour l&#8217;erreur 404 (page inexistante), l&#8217;erreur 403 (accès interdit) ou les erreurs 500 (problème serveur). La page en question sera affichée dans le navigateur du visiteur, avec une explication et parfois une aide ou un formulaire de recherche.</p>
<p>La page peut être un peu grosse mais <a href="http://www.sitepoint.com/article/error-handling-user-experience">elle a un rôle dans l&#8217;expérience utilisateur</a>. C&#8217;est parfois une page d&#8217;aide autant qu&#8217;une page d&#8217;erreur (pour les erreurs 404 par exemple). Jusque là il n&#8217;y a rien de criticable, au contraire : le contenu sur la page d&#8217;erreur est un vrai plus s&#8217;il est bien fait.</p>
<h3>De la taille des erreurs</h3>
<p>Mais quand l&#8217;erreur survient sur un appel javascript, une feuille de style ou une image ? Votre serveur renvoie probablement la même bonne grosse page HTML. C&#8217;est 4ko pour les plus petites (Yahoo, Google) mais plus souvent 8 à 10ko (Le Monde, pages dynamiques de Skyrock blog) voire plus (Microsoft avec 18ko). Dans ces cas là vos 15ko de contenu sont totalement inutiles. Ils sont téléchargés mais ne seront jamais affichés. Plus votre page d&#8217;erreur est petite, mieux c&#8217;est.</p>
<p>Vos liens en erreur n&#8217;ont pas plus de raison d&#8217;être faits vers des pages HTML que vers des javascript, des images ou des feuilles de style. Il est même probable que vos erreurs suivent le même ratio html/autre que vos requêtes habituelles, ce qui revient certainement à dire que les erreurs sur des balises <code>&lt;script&gt;</code>, <code>&lt;img&gt;</code>, <code>&lt;link&gt;</code> ou des <code>url()</code> dans les CSS sont plus fréquentes que les erreurs sur des liens classiques <code>&lt;a&gt;</code>. La majorité des contenus téléchargés suite à une erreur l&#8217;est inutilement.</p>
<p>Quand bien même votre page d&#8217;erreur doit aider l&#8217;utilisateur, <strong>elle doit aussi rester la </strong><strong>plus petite possible</strong> car le plus souvent votre contenu est inutile. Pire qu&#8217;inutile, il va occuper la bande passante et les fils de téléchargements de votre visiteur. Les 4ko de Yahoo sont raisonnables, Les 18ko de Microsoft ne le sont pas. Le site Légifrance fournit ainsi un logo, une description de l&#8217;erreur des liens vers la page d&#8217;accueil, la page précédente, le plan du site, la page de contact &#8230; le tout en moins de 1ko.</p>
<p>Si vous utilisez un <acronym title="content delivery network">CDN</acronym> (<a href="http://developer.yahoo.net/blog/archives/2007/04/high_performanc_1.html">et vous devriez</a>), les pages d&#8217;erreur sur ce dernier ont tout intérêt à contenir le strict minimum elles aussi. Selon toutes probabilité le visiteur ne les verra jamais. Celles du serveur statique de skyrock blog est par exemple d&#8217;à peine 120 octets. Sans en arriver forcément là, pensez à rester en dessous de 1ko.</p>
<h3>Des redirections</h3>
<p>Après une erreur 404 sur le site du premier ministre, nous arrivons sur la page d&#8217;accueil, 8ko. Ce n&#8217;est déjà pas glorieux mais c&#8217;est habituel. Par contre nous y arrivons après une redirection HTTP. Une redirection implique une seconde requête HTTP, avec tous les cookies.</p>
<p>Pour une latence de 40ms, 2ko de cookie et une page d&#8217;accueil de 8ko, sur une ligne 2mb/s en réception divisée en deux fils d&#8217;exécution, 512kb/s en émission, c&#8217;est 75ms pour la première requête et 135ms pour la seconde. À chaque erreur dans l&#8217;adresse d&#8217;une image, votre navigateur perdra 210ms à télécharger quelque chose qui lui est inutile. Les téléchargements suivants seront différés d&#8217;autant. Imaginez 5 images en erreur, c&#8217;est une seconde de perdue.</p>
<p>Sur le site du premier ministre c&#8217;est en réalité 300ms qui sont perdues car le serveur met un temps inacceptable à retourner la redirection. C&#8217;est d&#8217;autant plus dommage que même quand j&#8217;aurai effectivement affiché la page d&#8217;erreur, l&#8217;utilisateur ne comprendra pas pourquoi il arrive sur la page d&#8217;accueil et ne pourra pas corriger une adresse mal tapée. La règle est simple : ne faites <strong>aucune redirection sur vos pages d&#8217;erreurs</strong>.</p>
<h3>Du javascript</h3>
<p>Le cas du javascript est d&#8217;autant plus gênant. Lors du téléchargement d&#8217;un fichier Javascript, <a href="http://performance.survol.fr/2008/04/javascript-a-sa-place/">tout autre téléchargement sur la page est interrompu</a>. Le rendu et l&#8217;analyse de la page aussi. Si vous avez 300ms pour joindre votre page d&#8217;erreur comme dans le cas du site du premier ministre. C&#8217;est directement 300ms de plus pour afficher votre page principale si elle contient un lien javascript erroné.</p>
<p>Pire, votre navigateur retourne une page complète à la place du javascript. Comme les développeurs ont la mauvaise habitude de ne pas gérer correctement les types mimes, les navigateurs analysent parfois le contenu sans en tenir compte. Non content de bloquer pendant 300ms de téléchargement, votre navigateur va tenter d&#8217;analyser vos 8ko de html pour voir s&#8217;ils peuvent être interprétés comme du javascript. Suivant votre occupation processeur c&#8217;est autant d&#8217;attente en plus avant de débloquer l&#8217;analyse de la page.</p>
<p>Si vous pouvez vous le permettre, une solution peut être de détecter l&#8217;extension du fichier demandé. <strong>Si l&#8217;adresse finit en <code>.js</code>, alors renvoyez une page d&#8217;erreur vraiment minimale</strong>, de moins d&#8217;1ko, et sans redirection. Ce n&#8217;est pas idéal car peut être que l&#8217;adresse en erreur n&#8217;aura pas cette extension, mais cela couvre une majorité des cas.</p>
<h3>Du CSS</h3>
<p>Après avoir parlé de Javascript, il ne reste plus qu&#8217;à parler des feuilles de style. C&#8217;est Peter Frueh (encore un développeur web de Yahoo!) qui nous rappelle le comportement des navigateurs avec les images de fond en CSS : <a href="http://www.ajaxprogrammer.com/?p=33">Si vous laissez un </a><code><a href="http://www.ajaxprogrammer.com/?p=33">url()</a></code><a href="http://www.ajaxprogrammer.com/?p=33"> vide</a> pour une image de fond, le navigateur téléchargera la page HTML courante, comme pour un lien <code>&lt;a&gt;</code> avec un attribut <code>href</code> vide. Au lieu d&#8217;une petite image de fond de 2ko, c&#8217;est souvent 10ko qui seront téléchargés. C&#8217;est même 300ms de perdu pour le site du premier ministre.</p>
<p>Même pour les <code>&lt;link&gt;</code> et les <code>@import</code>, comme nous l&#8217;avons vu dans <a href="http://performance.survol.fr/2008/04/css-et-import/">le billet précédent</a>, le rendu est mis en attente. Quitte à faire une erreur dans l&#8217;adresse, autant que le rendu ne soit pas différé de 300ms.</p>
<p>Là aussi, <strong>détecter les extensions <code>.css</code>, <code>.png</code>, <code>.gif</code> et <code>.jpg</code> pour générer des pages d&#8217;erreurs minimales</strong> dans ces cas est probablement une bonne pratique.</p>
<h3>Des autres erreurs</h3>
<p>J&#8217;ai beaucoup parlé des erreurs 404, probablement parce que ce sont les plus courantes. Vous pouvez traiter les autres erreurs 4xx de la même manière.</p>
<p>Les erreurs 5xx sont toutefois un peu différentes. Elles montrent une erreur du serveur et le plus souvent ces erreurs sont persistantes et globales à tout le site. Si j&#8217;ai une erreur 500, il est tout à fait possible que je ne puisse pas atteindre une autre page.</p>
<p>Le plan du site ou le formulaire de recherche risque de générer des requêtes supplémentaires sur un site surchargé et/ou en erreur grave. S&#8217;il s&#8217;agit d&#8217;une erreur globale ou inconnue, prévoyez plutôt une page d&#8217;erreur minimale qui n&#8217;incitera pas votre visiteur à relancer des requêtes immédiatement (et bien entendu alertez immédiatement votre équipe de support par un dispositif d&#8217;alerte d&#8217;urgence).</p>
<p>Vous devriez utiliser un CDN, mais <strong>si vous ne le faites pas, évitez d&#8217;inclure des composants externes sur votre page d&#8217;erreur 500</strong>. Le javascript et le CSS indispensable doivent être directement dans la page HTML, les images devraient être évitées. C&#8217;est moche pour l&#8217;utilisateur mais le faire attendre un contenu qui ne viendra pas c&#8217;est encore pire.</p>
<h3>Quelques règles ?</h3>
<p>Vous voulez aller vite ? voici quelques bonnes pratiques :</p>
<ul>
<li>ne pas faire de redirection sur une erreur,</li>
<li>gardez des pages d&#8217;erreur petites (4ko est une bonne cible),</li>
<li>faites des pages d&#8217;erreur minimales sur vos CDN (moins de 1ko),</li>
<li>si l&#8217;adresse en erreur finit en <code>.js</code>, <code>.css</code>, <code>.png</code>, <code>.gif</code> ou <code>.jpg</code>, générez une page d&#8217;erreur minimale (1ko),</li>
<li>dans le cas d&#8217;une erreur serveur globale, ne faites pas de liens vers d&#8217;autres pages de votre site (plan, accueil, recherche) ou vers des composants sur le même serveur (javascript, css, images).</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://performance.survol.fr/2008/04/pages-d-erreur/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>CSS et @import</title>
		<link>http://performance.survol.fr/2008/04/css-et-import/</link>
		<comments>http://performance.survol.fr/2008/04/css-et-import/#comments</comments>
		<pubDate>Fri, 18 Apr 2008 18:17:39 +0000</pubDate>
		<dc:creator>Éric</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[@import]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[réseau]]></category>
		<category><![CDATA[téléchargement]]></category>

		<guid isPermaLink="false">http://performance.survol.fr/?p=21</guid>
		<description><![CDATA[Il y a peu on a vu fleurir des liens vers des propositions au groupe de travail CSS. Et en particulier une proposition de variables CSS. Ces variables peuvent être changées dynamiquement en javascript. Le rendu est alors refait avec &#8230; <a href="http://performance.survol.fr/2008/04/css-et-import/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Il y a peu on a vu fleurir des liens vers des propositions au groupe de travail <acronym title="cascading style sheet">CSS</acronym>. Et en particulier <a href="http://disruptive-innovations.com/zoo/cssvariables/">une proposition de variables CSS</a>. Ces variables peuvent être changées dynamiquement en javascript. Le rendu est alors refait avec la nouvelle valeur, partout où la variable était utilisée.</p>
<h3>La question des performances</h3>
<p>Si vous gérez plusieurs CSS sur une même page vous avez le choix entre faire un javascript qui va parcourir toutes vos feuilles de style à chaque changement pour reporter le changement (et faire attention à ne pas le faire pour les CSS externes que vous ne contrôlez pas), ou imbriquer vos feuilles de styles les unes dans les autres à coups de <code>@import</code>.</p>
<p>S&#8217;en suit <a href="http://ljouanneau.com/blog/2008/04/09/777-variables-en-css#c14166">quelques commentaires</a> sur <a href="http://ljouanneau.com/blog/">le blog de l&#8217;excellent Laurent Jouanneau</a> à propos du coût en performance de <code>@import</code>. C&#8217;est une syntaxe déconseillée un peu partout du point de vue des performances et j&#8217;ai entendu des choses étranges, comme le fait que les CSS en <code>@import</code> seraient téléchargées après tout le contenu, voire après le onload de la page, <a href="http://www.thewatchmakerproject.com/journal/461/import-considered-harmful">ou que ça bloque tout le navigateur au même titre qu&#8217;un <code>&lt;script&gt;</code></a>.<span id="more-19"></span></p>
<h3>Les tests</h3>
<p>Laurent étant dubitatif, les avis sur la question étant surtout des on-dits, me voilà à faire des tests. J&#8217;ai fait une page HTML qui charge deux CSS en <code>&lt;link&gt;</code> (<em>A1</em> et <em>B1</em>). Chaque CSS en link en charge une autre en <code>@import</code> (<em>A2</em> et <em>B2</em>) et tente d&#8217;appliquer quelques règles. Viennent ensuite du contenu HTML neutre mais suffisamment gros pour tenter de forcer le rendu du navigateur, et quelques images.</p>
<p>Du PHP me permet de régler des temps d&#8217;attente entre chaque ligne pour simuler des téléchargements lents et des délais aux diverses étapes. Un fichier journal me permet de savoir à tout moment quand une requête arrive sur mon serveur mais aussi quand un téléchargement s&#8217;arrête. Il y a d&#8217;autres outils pour ça mais le panneau réseau de Firebug donne des résultats totalement faussés, en tout cas sur les dernières versions beta. Préférez les vieilles bonnes solutions en fichiers de log.</p>
<h3>Les résultats</h3>
<p>Les résultats ne sont pas ceux que j&#8217;attendais, et pas ceux qu&#8217;on décrit dans les on-dits, mais je ne suis pas sûr qu&#8217;ils puissent être considérés comme meilleurs. J&#8217;ai testé la beta 5 de Firefox 3 et Microsoft Internet Explorer 6 dans leur configuration par défaut, les deux navigateurs ont réagit de la même façon.</p>
<ol>
<li>Le rendu de la page est mis en attente le temps que toutes les feuilles de styles soient téléchargées entièrement et analysé. J&#8217;ai eu beau mettre 100ko de HTML divers et 6 secondes de délai pour télécharger mes CSS, histoire de tenter de forcer la main au navigateur, mais rien à faire : le navigateur n&#8217;affiche rien tant qu&#8217;une feuille de style est en téléchargement. Je suis resté donc scotché sur la page précédente pendant presque 7 secondes, avant de voir toute la page s&#8217;afficher d&#8217;un coup.</li>
<li>La page s&#8217;affiche ensuite d&#8217;un coup. J&#8217;entend par là que dans mon journal je vois que le navigateur demande les images et la seconde CSS en <code>&lt;link&gt;</code> au serveur. Il n&#8217;attend pas pour ça la fin de la feuille de style. Le rendu est bloqué mais le navigateur analyse tout de même le HTML et lance les téléchargements nécessaires en tâche de fond. C&#8217;est déjà moins grave.</li>
<li>Les feuilles de style <em>A1</em> et <em>B1</em> (celles déclarées en <code>&lt;link&gt;</code>) sont téléchargées en parallèle, quand bien même le rendu est bloqué. On est dans le même cas que les images. Le navigateur attend patiemment la fin du téléchargement et de l&#8217;analyse de <em>A1</em> et <em>B1</em> pour respectivement initier les téléchargements de <em>A2</em> et <em>B2</em> (celles chargée via <code>@import</code> à partir des premières). Au lieu de faire du parallèle, nous voilà à faire du séquentiel. On double le temps d&#8217;attente et le rendu est toujours bloqué pendant ce temps là.</li>
<li>Pire, mes deux <em>A2</em> et <em>B2</em> sont ajoutées à la queue des téléchargements sans aucune priorité. C&#8217;est à dire que si <em>A1</em> et <em>B1</em> sont grosses ou si votre serveur met longtemps à répondre, la queue de téléchargement sera déjà encombrée d&#8217;une multitude d&#8217;images et d&#8217;objets externes. Il faudra télécharger tous ceux là avant de pouvoir télécharger <em>A2</em> et <em>B2</em>. Pendant ce temps votre rendu est toujours bloqué, en attente.</li>
</ol>
<h3>La conséquence</h3>
<p>Pour l&#8217;exemple : Vous avez une grosse CSS de 30ko qui en charge une autre plus petite de 5ko. Viennent ensuite une douzaine d&#8217;images de 3ko, des avatars par exemple. Vous souhaitez garder deux fichiers CSS parce que la grosse est spécifique à cette page et il serait dommage de pourrir la petite CSS générique juste pour ça. Vous accédez à tout ça avec une latence réseau honnête de 40ms, une liaison 2mb/s et Firefox 2 (donc deux fils de téléchargements d&#8217;1mb/s chacun).</p>
<p>Si vous utilisez <code>@import</code> vous aurez un rendu qui commencera après 325ms :</p>
<ul>
<li>Premier fil de téléchargement : la première CSS (0 à 65ms), l&#8217;image 3 (65 à 110ms), l&#8217;image 5 (110 à 155ms), l&#8217;image 7 (155 à 190ms), l&#8217;image 9 (190 à 235ms), l&#8217;image 11 (235 à 275ms), <strong>la seconde CSS (275 à 325ms)</strong></li>
<li>Second fil de téléchargement : l&#8217;image 1 (0 à 45ms), l&#8217;image 2 (45 à 90ms), l&#8217;image 4 (90 à 135ms), l&#8217;image 6 (135 à 175ms), l&#8217;image 8 (175 à 215ms), l&#8217;image 10 (215 à 255ms), l&#8217;image 12 (255 à 290ms)</li>
</ul>
<p>Avec deux <code>&lt;link&gt;</code> et sans <code>@import</code>, les deux téléchargements se font en parallèle. On commence donc à 65ms au lieu de 325ms. Les avatars se chargeront au fur et à mesure. Sachant que<a href="http://www.useit.com/papers/responsetime.html"> la différence de perception entre &laquo;&nbsp;attente&nbsp;&raquo; et &laquo;&nbsp;instantané&nbsp;&raquo; se situe vers les 100ms</a>, c&#8217;est justement ce qu&#8217;on vient de gagner. </p>
<p>Encore une fois, de plus, le calcul est très idéal : latence faible, connexion exploitée à fond, temps d&#8217;analyse et délais de réaction nuls, etc. En pratique il est courant d&#8217;avoir quelques fichiers qui dépassent les 150ms et une latence plus faible. Sur le blog de Laurent justement, qui contient justement plein de fichiers CSS et une dizaine d&#8217;images, j&#8217;ai une demi-seconde au total. Et un rendu qui serait bloqué une demi-seconde (ce qui n&#8217;est pas le cas chez lui) ça se perçoit, ça a une influence non négligeable. </p>
<h3>En vitesse</h3>
<p>Il manque à regarder ce que donne une feuille de style chargée par <code>@import</code> directement dans le HTML mais la conclusion du premier test est sans appel : pas de <code>@import</code> à l&#8217;intérieur d&#8217;une feuille de style.</p>
<p>Si d&#8217;aucuns veulent tester d&#8217;autres navigateurs où on testé le cas du <code>@import</code> à partir du HTML source, n&#8217;hésitez pas à poser un lien ou un commentaire.</p>
]]></content:encoded>
			<wfw:commentRss>http://performance.survol.fr/2008/04/css-et-import/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Compression avant transfert</title>
		<link>http://performance.survol.fr/2008/04/compression-avant-transfert/</link>
		<comments>http://performance.survol.fr/2008/04/compression-avant-transfert/#comments</comments>
		<pubDate>Tue, 15 Apr 2008 10:17:08 +0000</pubDate>
		<dc:creator>Éric</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[compression]]></category>
		<category><![CDATA[deflate]]></category>
		<category><![CDATA[gzip]]></category>
		<category><![CDATA[réseau]]></category>

		<guid isPermaLink="false">http://performance.survol.fr/?p=20</guid>
		<description><![CDATA[Après avoir parlé de minimisation, il est temps de parler de compression, la règle 4 des recommandations de l&#8217;équipe performance Yahoo!. Trop gros Une part importantes des téléchargements sont réalisés sur de simples fichiers textes : HTML, javascript, CSS, XML et &#8230; <a href="http://performance.survol.fr/2008/04/compression-avant-transfert/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Après avoir parlé de <a href="http://performance.survol.fr/2008/04/minimiser-le-javascript/">minimisation</a>, il est temps de parler de compression, <a href="http://developer.yahoo.net/blog/archives/2007/07/high_performanc_3.html">la règle 4</a> des <a href="http://developer.yahoo.com/performance/rules.html">recommandations de l&#8217;équipe performance Yahoo!</a>.</p>
<h3>Trop gros</h3>
<p>Une part importantes des téléchargements sont réalisés sur de simples fichiers textes : HTML, javascript, CSS, XML et JSON. Mis côte à côte ils peuvent représenter un poids non négligeable. C&#8217;est particulièrement vrai avec les bibliothèques javascript récentes. On dépasse alors les 50 ko pour la base, et plus si on ajoute les composants optionnels.</p>
<p>Un site classique avec Jquery c&#8217;est 25 ko pour le HTML, 10 ko pour les feuilles de style, 100 ko pour la bibliothèque javascript et encore bien 10 ko pour les fichiers javascript qui utilisent cette bibliothèque. La minification nous fait tomber respectivement à 15, 7, 50 et 6 ko, mais le total reste encore proche des 80 ko.<span id="more-18"></span></p>
<h3>Compresser avant envoi</h3>
<p>Tout est prévu, et il est possible de compresser nos fichiers avant de les envoyer, puis de les faire décompresser avant affichage par le navigateur. Cette fonctionnalité est gérée par une écrasante majorité des serveurs web et <a href="http://schroepl.net/projekte/mod_gzip/browser.htm">quasiment tous les navigateurs depuis Microsoft Internet Explorer 4</a>.</p>
<p>Lors de la transmission, c&#8217;est un fichier texte compressé qui est échangé. On peut compter que le poids est facilement divisé par deux sur un fichier qui a été minimisé au préalable mais ça peut aller jusqu&#8217;à un dixième du poids d&#8217;origine. 40 ko d&#8217;épargné, ce n&#8217;est pas la réussite de l&#8217;année mais <a href="http://www.ibm.com/developerworks/web/library/wa-httpcomp/">ça reste appréciable</a>.</p>
<h3>Auto-négociation</h3>
<p>Tout ça se base sur l&#8217;auto-négociation HTTP. Votre navigateur déclare qu&#8217;il sait gérer la compression avec une entête <code>Accept-encoding: gzip</code>. Le serveur la détecte, compresse son fichier HTML, et le renvoie avec une entête <code>Content-Encoding: gzip</code>. Tout est transparent pour l&#8217;utilisateur ou le navigateur. Si votre navigateur ne supporte pas la fonctionnalité, il n&#8217;enverra pas l&#8217;entête et recevra le contenu sans compression.</p>
<p>Pour les proxy les plus simples, ceux qui ne (dé)compressent pas les contenus en temps réel, le serveur ajoute une entête <code>Vary: Accept-encoding</code>. Le cache de ce contenu ne sera partagé que entre les navigateurs qui envoient la même entête <code>Accept-encoding</code> (c&#8217;est à dire quasiment tous).</p>
<p>L&#8217;auto-négociation fait très bien son travail. Il ne vous reste plus qu&#8217;à exclure les rares vieux navigateurs qui déclarent supporter la compression mais ont quelques bugs gênants. Si vous détectez ces navigateurs avec un support cassé vous pouvez ajouter <code>Vary: Accept-encoding, User-Agent</code>. </p>
<h3>Quels fichiers</h3>
<p>On compresse ainsi tout ce qui est fichier texte. On évite les images non vectorielles, qui sont en général déjà compressées avec des algorithmes spécifiques, ainsi que les fichiers binaires,  certains comme les fichiers OpenOffice sont déjà le résultat d&#8217;une compression et les autres ont trop souvent un taux de compression assez faible.</p>
<p>Un tri très rapide peut être fait à partir des types mime des fichiers : on compresse tout ce qui est en <code>text/*</code> et on laisse le reste tel quel, en particulier les images. Si vous voulez faire de la gestion fine vous pouvez aussi compresser les fichiers Microsoft Office .doc, .ppt et .xls (qui se compressent très bien).</p>
<h3>Quel format et quel module</h3>
<p>Il y a deux formats de compressions pour HTTP, tous deux supportés correctement : <a href="http://en.wikipedia.org/wiki/Gzip">gzip</a> (RFC 1951 et 1952), <a href="http://en.wikipedia.org/wiki/Deflate">deflate</a> (RFC 1951 et 1950) et <a href="http://en.wikipedia.org/wiki/Compress">compress</a>. Ce dernier est pour ainsi dire inutilisé dans les échanges Web. Les deux autres sont à peu près équivalents. Pour être précis <a href="http://www.gzip.org/deflate.html">gzip est simplement du deflate</a> avec quelques meta-données.</p>
<p>Pour le serveur web Apache, cela se traduit dans deux modules : <a href="http://sourceforge.net/projects/mod-gzip/">mod_gzip</a> et <a href="http://httpd.apache.org/docs/2.0/mod/mod_deflate.html">mod_deflate</a>. Le premier est habituel sous Apache 1.3, le second par défaut est fourni avec Apache 2.0. Les performances sont similaires, même si l&#8217;algorithme utilisée par mod_gzip donne des fichiers légèrement plus petits (mod_deflate utilise la bibliothèque système zlib alors que mod_gzip utilise son propre code). La différence entre les deux se joue plutôt sur les fonctionnalités des implémentations des deux modules. Mod_gzip propose en effet quelques possibilités en plus.</p>
<p>Pour IIS j&#8217;ai vu passer des liens vers <a href="http://www.port80software.com/products/zipenable/">zipenable</a> et <a href="http://www.port80software.com/products/httpzip/">httpZip</a> mais <a href="http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/25d2170b-09c0-45fd-8da4-898cf9a7d568.mspx?mfr=true">il semble qu&#8217;un support soit inclus par défaut</a>. PHP a aussi la directive de configuration <code>zlib.output_compression</code> pour compresser son résultat avant l&#8217;envoi au navigateur, mais il est probablement plus cohérent de passer par le serveur web pour gérer de genre de questions.</p>
<h3>Les performances</h3>
<p>Pour le client c&#8217;est entre 50 et 90% du traffic réseau sur les fichiers textes et Microsoft Office qui est épargné. Tout cela n&#8217;est bien entendu pas neutre pour le serveur. On parle souvent de 5% d&#8217;occupation processeur pour compresser les contenus. Donner un chiffre est hasardeux car cela dépend trop du serveur, du matériel, des fichiers à compresser et de la charge cpu.</p>
<p>Il est pourtant possible de dire que la charge supplémentaire ne sera pas très importante en regard du gain réseau. C&#8217;est d&#8217;autant que le traffic réseau est cher, la puissance processeur ne l&#8217;est plus tant que ça. Si vous vous contentez des fichiers textes et fichiers Microsoft Office, que vous ne lancez pas de compression pour des fichiers trop petits (1ko) ou (pour mod_gzip) des fichiers trop gros, vous avez peu de chance de faire des contre-performances.</p>
<h3>La configuration et les options</h3>
<p>Pour vous aider sur mod_gzip et mod_deflate vous avez la possibilité de préciser un niveau de compression avec neuf valeurs prédéfinies de 1 une compression minimum à 9 pour une compression maximum. Il est souvent conseillé de se fixer entre 4 et 6. Monter à 9 occupe beaucoup le processeur pour une différence de taille minime. Aux valeurs les plus faibles votre serveur n&#8217;est quasiment pas occupé mais le gain de taille est déjà visible.</p>
<p>Pour ceux qui ont le plus gros traffic d&#8217;autres stratégies sont possibles. Les fichiers compressés peuvent être stockés sur le disque pour éviter d&#8217;être recalculés à chaque accès par exemple. Il est même possible de pré-compresser les fichiers et opérer à l&#8217;inverse : faire faire décompresser les fichiers au serveur pour les quelques rares navigateurs qui ne savent pas gérer la compression.</p>
<h3>Et vous ?</h3>
<p>Un doute sur votre serveur ? deux pages en ligne vous permet de tester votre site : <a href="http://www.whatsmyip.org/mod_gzip_test/">le mod_gzip_test</a> et <a href="http://www.gidnetwork.com/tools/gzip-test.php">le gzip_test</a>. Faites bien attentions aux résultats de Firebug qui peuvent être modifiés par votre proxy, votre anti-virus, vos anti-spyware, vos pare-feux, vos extensions et les outils de protection de la vie privée que vous pourriez avoir : tout ça peut intervenir avant Firebug et décompresser le flux pour le filtrer avant de le renvoyer.</p>
<p>Vous avez aussi <a href="http://www.port80software.com/tools/compresscheck.asp">compression test</a> et <a href="http://www.port80software.com/products/httpzip/bandwidthcalc">bandwith calc</a> de port80. Le premier télécharge une page et calcule le gain que vous auriez si le contenu était compressé. Avec cette mesure, le second outil vous permet de calculer les économies sur la facture réseau. C&#8217;est là que vous verrez vite si échanger du réseau contre du processeur est intéressant ou pas.</p>
]]></content:encoded>
			<wfw:commentRss>http://performance.survol.fr/2008/04/compression-avant-transfert/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
