Amélioration du temps d’affichage du site.

Depuis quelques temps mon serveur commençait à prendre un peu trop de charge. Le load average du serveur tournait en permanence au-dessus de 20 (alors qu’il n’aurait pas dû passer au dessus de 4).  La faute à quelques scripts un peu trop gourmand en CPU et surtout en lecture/écriture sur disque.

Le plus important écrivait 70Mo par minute, soit plus d’1Mo par seconde. A ça s’ajoutait un peu plus pour la lecture. D’autres scripts accédaient non stop à une base de données contenant 500Mo de data diverses… Et comme je suis loin d’être un pro de l’optimisation je vous laisse imaginer le résultat.

J’ai donc été obligé de changer de machine, de réécrire mes scripts et de faire quelques petites optimisations. Dans l’ordre :

Location d’un serveur plus puissant. Un HG-2010 SSD chez OVH. SSD car les accès disques sont importants, et le produit proposé par OVH me semblait pas trop mal. J’ai en plus pris l’option 48Go pour la RAM, tant qu’à faire autant le faire en grand.

Allégement de la base de données est stockant le résultat des requêtes en RAM avec Memcached (d’où l’option 48Go). De mémoire j’ai alloué 24Go à Memcached, de quoi mettre beaucoup de données.

Utilisation du module mod_expires d’apache. J’ai appris que ce module pouvait faire en sorte de mettre en cache des données dans le navigateur de mes chers visiteurs. Les images sont donc stockées 1 mois ainsi que les fichiers CSS et JS. Pour éviter les bugs avec un CSS ou un JS pas à jour, à chaque mise à jour je change les noms (fichier.css?version=1.15 par exemple). J’ai fait quelques tests avec Firebug + page Speed de Google et le gain est loin d’être négligeable. Le tout peut se gérer avec quelques lignes dans le .htaccess

<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css “access plus 1 month”
ExpiresByType text/javascript “access plus 1 month”
ExpiresByType application/x-javascript “access plus 1 month”
ExpiresByType application/javascript “access plus 1 month”
ExpiresByType image/x-icon “access plus 1 month”
ExpiresByType image/ico “access plus 1 month”
ExpiresByType image/vnd.microsoft.icon  “access plus 1 month”
ExpiresByType image/png “access plus 1 month”
ExpiresByType image/gif “access plus 1 month”
ExpiresByType image/jpeg “access plus 1 month”
ExpiresByType image/jpg “access plus 1 month”
ExpiresByType application/x-shockwave-flash “access plus 1 month”
</IfModule>

Pour les quelques images dynamiques j’ajoute un header en PHP

header(“Pragma: public”);
header(“Cache-Control: maxage=”.$expireGraph);
header(‘Expires: ‘ . gmdate(‘D, d M Y H:i:s’, time()+$expireGraph) . ‘ GMT’);
header(“Content-type: image/png”);

Mes 10 fichiers CSS et 13 fichiers js ont été regroupés et compressés avec minify. Je gagne 21 hits sur chaque visiteur + des pages qui gagnent encore en vitesse d’affichage.

J’ai placé le code Google Analytics asynchrone. Je n’ai pas mesuré l’impact, je me fie à la compétence des ingénieurs de Google. Seul petit hic, je n’ai plus d’évènement et je n’ai pas encore trouvé d’où provient le bug… Il faut dire que je n’ai pas cherché longtemps.

Toutes mes anciennes données en cache – celles qui prenaient 1Mo/ seconde en écriture disque – sont passées en RAM avec memcached. Une vrai révolution dans ma façon de coder mais la forte diminution des accès disque a fait passer à lui seul le load average de la machine à 10 (sur le nouveau serveur) à 0.5/2.

Il me reste encore à utiliser les sprites dans les CSS. Mais pour ça il me faudra un peu de temps. Les images et moi ça fait 2. Quand ce sera fait je devrais gagner une vingtaine de hits par visiteurs… Encore un point non négligeable pour la charge serveur et la rapidité du site.

Le bilan de tout ça ?

D’après Google le temps d’affichage moyen d’une page par un visiteur est passé de 6 à 4 secondes (gain >30%). J’ai bon espoir de descendre sous les 3 secondes d’ici quelques temps. Je serais de toute façon limité à cause du temps d’affichage des bannières pub et du marqueur Xiti (d’ailleurs je suis en train de réfléchir à l’enlever)

Google passe moins de 0.5 seconde à crawler une page contre 1.5 seconde avant mes optimisations diverses.

Petite déception, je n’ai pas de modification du nombre de pages vues par visites ou une diminution significative du taux de rebond. Il faut croire que mes visiteurs étaient patient…

Il parait que la rapidité des sites va entrer dans l’algo du classement des sites dans le moteur de recherche. C’est un bon argument pour aller le plus loin possible sur cette route.crawl-google

7 thoughts on “Amélioration du temps d’affichage du site.

  1. Merci pour toutes ces infos, je suis justement en train de travailler dessus.
    J’ai mis en place spritecss, petit conseil, tu peux utiliser smartspritecss http://csssprites.org/
    Assez facile à utiliser et pas besoin d’etre un expert css pour l’utiliser.

  2. Arnaud,

    Cool. Merci pour ton retour d’expérience bien détaillé. Une mine d’or pour moi et je pense que je vais mettre en œuvre le mod_expires sur cbanque.

    Pour info, cbanque (lui aussi sur un serveur avec disque SSD) est plus rapide que 59% des sites (d’après Google Webmasters) avec une moyenne de chargement de 2,4s. Une moyenne obtenue avec de nombreuses pages sans accès direct à SQL.

  3. Fred, Une partie du temps de chargement est certainement due au marqueur de Xiti. Je vais faire quelques mesures avec/sans pour voir si je le garde ou non. Les bannières pub sont aussi assez longues à charger, malheureusement je ne peux rien modifier.

    Nil, un proxy ne devrait pas me faire gagner beaucoup de temps. Memcached à déjà fortement réduit le temps de construction des pages dynamiques. De plus je ne voudrais pas ajouter une couche de cache sur du cache.

  4. J’adore ces exp d’optimisations de sites. Beaux résultats (et beau matos, le HG SSD avec 48Go RAM, ça envoie du pâté).

    Les pubs… Une vraie plaie. Sans compter le marqueur Xiti comme tu dis, mais aussi le bouton feedburner…

    Une exemple avec la page d’accueil d’ADNPC :
    Cache navigateur vide : 4,90s
    Cache navigateur plein : 2,68s (cad mes images, js et css sont en cache dans le client)
    Donc, moins les 400ms de la requête de la page (qui met que 180ms à se générer, soit dit en passant…), ça veut dire que les pubs et autres babioles me coûtent 2,20s !

    J’ai optimisé à fond le temps de génération de page (cache par partie…), le reste était accessoire (juste expire & gzip, ça joue déjà beaucoup).

    Mais il y a des trucs, on peut pas jouer dessus. Comme tu dis, pour les pubs, on peut pas faire autrement. On peut se dire que quand les visiteurs sont fidèles, les bannières sont en cache chez eux, ils se tapent juste les appels pour les stats…

    Sinon, à mon avis, Google prend déjà en compte le temps de chargement de la page dans son algorithme, et depuis longtemps. S’ils nous montre la courbe dans les stats d’indexation, c’est pas pour rien. Après, depuis récemment, ils nous montre une courbe avec le temps “overall” (ie avec les images, les js…), donc à mon avis, c’est pas pour rien non plus…

  5. Les bannières ne peuvent pas être en cache. Adsense ne le permet pas et mon annonceur non plus (ce sont des bannières tournantes).

    Sous les 3 secondes pour l’affichage d’une page on est quand même bien rapide. C’est assez confortable. Mais c’est quand même mieux d’être dans les 50% de sites les plus rapides que faire parti des plus lents…

Comments are closed.