OVH Cloud OVH Cloud

PHP: optimiser la génération de pages très dynamiques

28 réponses
Avatar
Patrick 'Zener' Brunet
Bonjour.

J'aimerais avoir quelques retours d'expérience sur l'optimisation des pages
fortement dynamiques en PHP.

Je cherche toujours pourquoi mon site (www.ipzb.fr) est si lent à charger,
même pour les pages les plus légères.

Pour l'histoire:
- il n'y a pas de requête SQL ni de connexion à des serveurs tiers,
- le sessionning existe pour toutes les pages (gestion d'un contexte
visiteur) mais il est fait avec un système de mini-fichiers très optimisé,
- l'URL rewriting est innocent, j'avais essayé de le désactiver sans
amélioration.

Le site est hébergé par 1and1. Ils ont une réputation de lenteur, mais à ce
point c'est déprimant.

L'extension de Firefox nommée LoadTimeAnalyser montre que, même pour une
page de base et en pleine session, on passe son temps à attendre le serveur,
le transfert des données étant lui presque instantané.
Voyez ce chronogramme (HTML pur):
http://cjoint.com/?lssEIBsuuz

La caractéristique de ce site est que les pages contiennent une forte
proportion d'éléments insérés par du PHP.
Donc il y a des <?php echo GetMachin(); ?> en assez grand nombre au milieu
du HTML.

Par contre les fonctions GetMachin() utilisent au maximum des éléments
précalculés, et à défaut ne font que des opérations très simples
(arithmétique, concaténation de petites chaînes...). Beaucoup ne font même
rien du tout et rendent une chaîne vide avec les options de base du site.

Il y a un bruit qui court selon lequel la primitive echo aurait un bug sur
certains moteurs PHP, dont celui utilisé par 1and1 (j'ai lu ça sur un forum,
invérifiable).

De toute manière, je vois mal comment optimiser davantage: le truc qui
consiste à insérer des fichiers HTML plutôt que de faire du echo ne
s'applique qu'à des tronçons un peu gros, pas à des chaînes de 20
caractères. Et pour les gros tronçons je pratique déjà.
Et PHP en principe c'est fait pour ça,

J'ai même des doutes sur la part du temps de calcul: certains temps
d'attente de plus d'une seconde correspondent à des éléments qui ne sont pas
générés (simple readfile avec 3 headers devant)...
Par exemple les images à la fin du chronogramme, dont le
mArrowR.gif par exemple: 1,2s pour 265 octets :o)

J'aimerais bien trouver un moyen d'avoir un chronogramme complet, montrant
tout le timing de requête+génération de la page avec tous ses éléments au
niveau du serveur... Vous avez une idée sur la méthode ?

Savez-vous aussi comment ça se passe au niveau des fichiers susceptibles
d'être inclus en read-only dans chaque requête HTTP (un mini script PHP de
définitions par exemple) - c'est mis en cache ou il y a risque de bottleneck
?

Merci de vos conseils (dans la mesure ou ce n'est pas "fais du HTML de
base", je sais faire aussi mais c'est hors-sujet ;-).

--
Cordialement.
--
/**************************************************\
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
\**************************************************/

10 réponses

1 2 3
Avatar
Denis Beauregard
Le Tue, 20 Nov 2007 23:44:02 +0100, "Patrick 'Zener' Brunet"
écrivait dans
fr.comp.infosystemes.www.auteurs:

Bonsoir.

"Denis Beauregard" a
écrit dans le message de news:
Le Sun, 18 Nov 2007 19:20:41 +0100, "Patrick 'Zener' Brunet"
écrivait dans
fr.comp.infosystemes.www.auteurs:

>Merci de vos conseils (dans la mesure ou ce n'est pas "fais du HTML
>de base", je sais faire aussi mais c'est hors-sujet ;-).

Mais si tu recodais une page en HTML, tu pourrais voir si c'est
vraiment le PHP qui est lent ou autre chose, ce qui te ferait
gagner beaucoup de temps si c'est autre chose...




En fait la structure du site fait qu'il n'est pas simple du tout d'y insérer
une page hors-layout, en pur HTML.



Pourtant, il suffirait d'enregistrer une page, de la renommer en .html
et de la relire...

Bon, entre temps j'ai pu mesurer les performances de la génération PHP
elle-même.



Une façon simple : une boucle et faire 10, 100, 1000 itérations, etc.


Denis
Avatar
Patrick 'Zener' Brunet
Bonsoir SAM.

"SAM" a écrit dans le message
de news: 4741953f$0$25934$
Patrick 'Zener' Brunet a écrit :
>
> J'aimerais avoir quelques retours d'expérience sur l'optimisation des


pages
> fortement dynamiques en PHP.

Il serait peut-être judicieux de passer sur le NG du PHP ?




Sais pas encore, ça ressemble de plus en plus à de l'inside Apache, et comme
c'est un hébergement mutualisé, je n'aurai pas vraiment la main...

- les sessions ont-elles besoin de se référer à *des* fichiers ?
(n'y a t'il pas de redondances à ce niveau ?)
Le serveur ne gère t-il pas tout seul les sessions ?



Une session, c'est un ID unique qui circule et qui désigne des données de
contexte résidentes sur le serveur.
C'est ce que j'ai fait au plus près de mon besoin.

- le cache PHP du serveur est-il bien mis à profit ?



C'est pas dans la doc mais ça en a l'air... j'ai même activé une compression
du texte mais sans noter de gain significatif.

- des cookies sont-ils mis en actions ?



Oui, un seul si pas désactivés, sinon l'ID de session transite dans l'URL.
Du classique.


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

sinon ? :
<http://www.websiteoptimization.com/services/analyze/>




J'ai déjà passé des heures à fouiller le Web moi aussi...

> Voyez ce chronogramme (HTML pur):
> http://cjoint.com/?lssEIBsuuz

Il m'apparait surtout qu'il y a vraiment beaucoup de choses à charger,
qu'entre chaque groupe de composants il pourrait il y avoir un code
serveur dynamique qui réfléchi



En fait l'idée c'est qu'il charge les données de session avec les options de
l'utilisateur (220 octets),
il y fait quelques mises à jour avant de les sauvegarder,
puis il génère la page demandée avec des éléments calculés dedans....


N'y aurait-il pas moyen de grouper les réflexions ?



L'accès à la session est forcément refait à chaque requête HTTP "majeure"
(le HTML et les CSS), avec modification uniquement pour le premier accès.

D'en mettre éventuellement le résultat dans un temp ou cooky
et se servir de ces tampons pour construire la page à afficher ?



Il y aurait gain seulement si le même utilisateur (même configuration)
redemande la même page, sinon le coût d'assemblage des tronçons fixes et des
inserts calculés serait prohibitif AMHA. Et il faudrait aussi faire le
ménage...

Bien que si la routine de départ a été optimisée en cache du serveur,
échoyer par ci par là les variables pré-calculées ne devrait pas freiner




J'aimerais bien savoir comment je pourrais précompiler mon PHP sur ce
serveur, et si ça vaut le coup...

Finalement (voir mes mesures d'aujourd'hui), le temps de calcul apparaît
très faible, ce qui me console un peu, je me suis donné assez de mal pour
programmer ça en optimisant à mort.
Le problème vient d'ailleurs...

> La caractéristique de ce site est que les pages contiennent une forte
> proportion d'éléments insérés par du PHP.
> Donc il y a des <?php echo GetMachin(); ?> en assez grand nombre
> au milieu du HTML.

à mon idée ça ne joue pas si c'est juste écrire des variables (et qu'il
n'y a pas à les recalculer)

> Par contre les fonctions GetMachin() utilisent au maximum des éléments
> précalculés,

tout dépend de où il faut que le php court pour aller trouver ou
retrouver ces près-calculs, non ?




Pas de recherche ni de recalcul inutile, j'y ai veillé, c'est ma religion.

<?=$ma_variable ?>
fonctionne-ce ? (peut-être + rapide ?)
faut voir aussi ce que contient cette variable ?




On parle de gains en µsecondes, la je suis à l'échelle 1000 :-(

> De toute manière, je vois mal comment optimiser davantage: le truc qui
> consiste à insérer des fichiers HTML plutôt que de faire du echo ne
> s'applique qu'à des tronçons un peu gros, pas à des chaînes de 20
> caractères. Et pour les gros tronçons je pratique déjà.
> Et PHP en principe c'est fait pour ça,

tu peux aussi printer l'ensemble de la page
(bonjour le boulot !)



C'est presque ce que j'ai fait.

Je viens de re-essayer
- je ne sais ce qu'il y a dans la page d'arrivée qui calcule la config
et qui tarde à envoyer la suite



C'est pas du calcul, c'est de l'attente, et c'est ça qui m'énerve :-(

- la page d'accueil se charge assez rapidement (j'ai déjà tout dans le
cache de mon navigateur) encore que, vu que la page semble ne pas
être très garnie ... (quoi que 83ko tt de même)



Il y a les logos, dont le gros IPZB. Le ratio des images est plus faible sur
les autres pages.

- passé à une autre page, bon oui ça a l'air d'aller
sauf que ... curieusement ... après l'affichage global, des trucs
continuent à s'immiscer dans les lignes déjà là ...




Je vais essayer de faire du preload des images en JS quand il est actif,
mais c'est pas simple à cause de la séparation contenu/mécanique.

Il me semble curieux que les appels aux JS et CSS externes soient des php.
Ne force-ce pas à :
- recalculs systématiques de ces sorties de JS ou CSS
- non mise en cache du navigateur de ces sorties ?



Je me posais la question, je ne sais pas comment le navigateur voit les
choses.
J'ai activé l'URL rewriting, désormais tout ça a l'air statique côté
client...

Ne serait-il pas plus simple d'échoyer directement l'url du fichier à
charger ? (puisqu'elle figure en variable de l'url, elle doit sortir de
qque part ET a déjà été calculée par ailleurs, ça me semble une
redondance et une possibilité de freinage) (est-ce que tout ça n'est-il
pas disponible une fois pour toute dans sa session ?)



Pour tous les élements fixes, c'est ce que j'attends du cache...
Pour les éléments à variantes (HTML, CSS et certaines images), j'ai eu des
problèmes avec le cache intermédiaire de mon employeur :-)
Il y a une dépendance à l'ID de session et j'ai aussi dû rajouter un
roll-count dans l'URL pour forcer la prise en compte des changements
d'options dans une même session !!!

Pas simple...

Merci pour ces idées.

--
Cordialement.
--
/**************************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
**************************************************/
Avatar
Olivier Miakinen
Le 21/11/2007 00:37, Patrick 'Zener' Brunet répondait à SAM :

- le cache PHP du serveur est-il bien mis à profit ?



C'est pas dans la doc mais ça en a l'air...



Si je ne m'abuse, il ne peut pas y avoir de mise en cache d'une page
générée par PHP à moins que tu ne calcules toi-même les paramètres de
cache qui vont bien, et que tu ne les envoies toi-même au moyen de
quelques appels à la fonction header().

Tout ceci me semble assez contradictoire avec ton « ça en a l'air » qui
laisse supposer que tu espères que ça se fasse tout seul...
Avatar
Patrick 'Zener' Brunet
Bonsoir.

"Olivier Miakinen" <om+ a écrit dans le message de news:
4743856f$
Le 21/11/2007 00:37, Patrick 'Zener' Brunet répondait à SAM :
>
>> - le cache PHP du serveur est-il bien mis à profit ?
>
> C'est pas dans la doc mais ça en a l'air...

Si je ne m'abuse, il ne peut pas y avoir de mise en cache d'une page
générée par PHP à moins que tu ne calcules toi-même les paramètres
de cache qui vont bien, et que tu ne les envoies toi-même au moyen de
quelques appels à la fonction header().

Tout ceci me semble assez contradictoire avec ton « ça en a l'air »
qui laisse supposer que tu espères que ça se fasse tout seul...



Oh, je ne crois pas à la chance :-)

J'expliquais que le contenu des pages est farci d'éléments dynamiques, donc
la mise en cache de la page toute calculée n'aurait pas d'intérêt sauf pour
un utilisateur particulier qui la recharge plusieurs fois sans changer ses
options. En contrepartie il faudrait faire ce pari perdant pour tous les
autres.

Par contre, et c'est-là le sens de ma réponse, on pourrait imaginer que le
PHP écrit humainement (proprement) dans les scripts soit conservé par le
serveur sous une forme précompilée, et aussi que le serveur mette en cache
les éléments fixes tels que les images une fois dotées de leurs headers, les
Javascripts, etc.

J'ai cherché comment lui dire de faire ça, et j'ai surtout trouvé des outils
à installer sur le serveur dont on a la gestion, alors que le mien est
mutualisé. Quant à la doc, sa teneur est plutôt commerciale que technique.
Comme il s'agit d'un hébergeur qui se veut PRO, je suppose que "ça en a
l'air". C'est vrai que je m'en contente mal :-/

Par contre j'ai fait tout mon possible pour bien piloter le cache du
navigateur et aussi celui du proxy d'entreprise.

--
Cordialement.
--
/**************************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
**************************************************/
Avatar
Patrick 'Zener' Brunet
Bonsoir.

"Denis Beauregard" a
écrit dans le message de news:
Le Tue, 20 Nov 2007 23:44:02 +0100, "Patrick 'Zener' Brunet"
écrivait dans
fr.comp.infosystemes.www.auteurs:
>"Denis Beauregard"


a
>écrit dans le message de news:



>> Le Sun, 18 Nov 2007 19:20:41 +0100, "Patrick 'Zener' Brunet"
>> écrivait dans
>> fr.comp.infosystemes.www.auteurs:
>>
>> >Merci de vos conseils (dans la mesure ou ce n'est pas "fais du HTML
>> >de base", je sais faire aussi mais c'est hors-sujet ;-).
>>
>> Mais si tu recodais une page en HTML, tu pourrais voir si c'est
>> vraiment le PHP qui est lent ou autre chose, ce qui te ferait
>> gagner beaucoup de temps si c'est autre chose...
>
>En fait la structure du site fait qu'il n'est pas simple du tout d'y


insérer
>une page hors-layout, en pur HTML.

Pourtant, il suffirait d'enregistrer une page, de la renommer en .html
et de la relire...




Oui, mais les répertoires sont protégés et donc inaccessibles en HTTP, la
prise en main commence dès le répertoire de base, les chemins apparents des
images et autres sont fictifs (URL rewriting), etc.

J'essaierai de monter une structure 100% HTML en parallèle au site lui-même,
mais ça se fait pas en 10mn ou alors ça ne sera pas représentatif.

--
Cordialement.
--
/**************************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
**************************************************/
Avatar
Olivier Miakinen
Le 21/11/2007 21:28, Patrick 'Zener' Brunet a écrit :

J'expliquais que le contenu des pages est farci d'éléments dynamiques, donc
la mise en cache de la page toute calculée n'aurait pas d'intérêt [...]



Y compris pour la « background-image » chargée par la feuille de style ?
Avatar
Patrick 'Zener' Brunet
Bonsoir (nuit).

"Olivier Miakinen" <om+ a écrit dans le message de news:
4744d728$
Le 21/11/2007 21:28, Patrick 'Zener' Brunet a écrit :
>
> J'expliquais que le contenu des pages est farci d'éléments dynamiques,
> donc la mise en cache de la page toute calculée n'aurait pas d'intérêt
> [...]

Y compris pour la « background-image » chargée par la feuille de style ?



Comprends pas... Le fond est uni, il n'y a aucune background-image dans tout
le site, sauf quelques GIFs de moins de 1Ko du genre des flèches de
navigation, installées dans des petits spans en milieu de texte.

L'attribut pour le fond est forcé à url(null) pour IE, c'est une partie d'un
hack connu pour éviter que le menu dans sa forme escamotable ne sautille
quand on scrolle la page (ça va avec le cssfixed.htc).

Sinon ce qu'il y a de plus gros comme image dans cette page Home, c'est le
logo IPZB (22Ko pour la résolution maximale), mais c'est hors-sujet.

--
Cordialement.
--
/**************************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
**************************************************/
Avatar
Olivier Miakinen
Le 23/11/2007 01:24, Patrick 'Zener' Brunet a écrit :
>
> J'expliquais que le contenu des pages est farci d'éléments dynamiques,
> donc la mise en cache de la page toute calculée n'aurait pas d'intérêt
> [...]

Y compris pour la « background-image » chargée par la feuille de style ?



Comprends pas... Le fond est uni, il n'y a aucune background-image dans tout
le site, sauf quelques GIFs de moins de 1Ko du genre des flèches de
navigation, installées dans des petits spans en milieu de texte.



Cf

<cit.>
et un autre truc qui me chagrine : je ne sais pas comment les
navigateurs peuvent interpréter les feuilles de style alors que celles
ci ne sont pas entièrement chargées puisque requête php... et qui
contiennent aussi des requêtes à l'intérieur :
background-image:
URL('/getdata.php?type=cssimage&nameÞfault/Images/RedPin.gif');
</cit.>
Avatar
Patrick 'Zener' Brunet
Bonsoir.

"Olivier Miakinen" <om+ a écrit dans le message de news:
4746a879$
Le 23/11/2007 01:24, Patrick 'Zener' Brunet a écrit :
>> >
>> > J'expliquais que le contenu des pages est farci d'éléments


dynamiques,
>> > donc la mise en cache de la page toute calculée n'aurait pas


d'intérêt
>> > [...]
>>
>> Y compris pour la « background-image » chargée par la feuille de style


?
>
> Comprends pas... Le fond est uni, il n'y a aucune background-image dans


tout
> le site, sauf quelques GIFs de moins de 1Ko du genre des flèches de
> navigation, installées dans des petits spans en milieu de texte.

Cf

<cit.>
et un autre truc qui me chagrine : je ne sais pas comment les
navigateurs peuvent interpréter les feuilles de style alors que celles
ci ne sont pas entièrement chargées puisque requête php... et qui
contiennent aussi des requêtes à l'intérieur :
background-image:
URL('/getdata.php?type=cssimage&nameÞfault/Images/RedPin.gif');
</cit.>



OK, le 21/11 j'ai activé le rewriting pour ces ressources, donc maintenant
elle apparaît comme:
URL('/cssimage/Default/Images/RedPin.gif').

Ca permet au navigateur de ne plus se poser de question sur sa nature
dynamique (s'il y avait lieu), même si au niveau du serveur elle est
toujours injectée par le getdata.php qui ne fait rien d'autre (pour des
histoires de chemins et de headers "expire" notamment ).

A part ça, c'est l'une de ces petites choses dont je parlais: 101 octets.
Elle est placée dans un background-image parce qu'elle fait partie du look
décrit par la CSS, et pas du contenu au sens sémantique.
De toute manière, je ne vois pas comment le fait de mettre la page en cache
pourrait constituer une optimisation à ce niveau, elle ferait toujours
l'objet d'une requête HTTP séparée qui serait servie de la même manière.

Je reviens sur mes mesures: elles montrent que le problème n'est pas au
niveau de la génération des contenus, qui est presque marginal.
En fait il y a un temps d'attente parasite qui représente 80% du délai.
Qu'est-ce qui se passe sous la plume de l'apache, est-ce qu'il roupille ? Là
est la vraie question, et je sèche :-@

--
Cordialement.
--
/**************************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
**************************************************/
Avatar
Denis Beauregard
Le Wed, 21 Nov 2007 21:33:41 +0100, "Patrick 'Zener' Brunet"
écrivait dans
fr.comp.infosystemes.www.auteurs:

J'essaierai de monter une structure 100% HTML en parallèle au site lui-même,
mais ça se fait pas en 10mn ou alors ça ne sera pas représentatif.



Je ne comprends pas pourquoi c'est si difficile. Pour moi,
l'opération est la suivante :

1- j'ouvre la page avec Seamonkey
2- je copie la page au complet avec aussi Seamonkey
(ctrl-A, ctrl-C)
3- je crée une nouvelle page vide avec Seamonkey
4- je recopie la page dans la page vide (ctrl-V)
5- j'enregistre la page
6- je la place sur le serveur.

Ceci dit, je ne connais pas les commandes de Apache, mais cela
doit pouvoir se trouver.

http://httpd.apache.org/docs/trunk/
http://httpd.apache.org/docs/trunk/mod/quickreference.html

Je me rappelle qu'on pouvait avoir des conditions et des include
dans la page html. Il y a peut-être moyen d'injecter l'heure
courante.

Autrefois, j'avais 2 domaines sur le même serveur. Un était
www.genealogie.com et l'autre www.francogene.com . Avec
Apache, je pouvais choisir le fichier affiché avec les énoncés
suivants. Il y a peut-être moyen d'injecter l'heure exacte que
l'on pourra comparer avec celle du fichier log.

<!--#if expr="${SERVER_NAME} = /genealogie.com/" -->
<!--#include file="index_fr.htm" -->
<!--#else -->
<!--#include file="index_en.htm" -->
<!--#endif -->

Je suis passé à PHP ves 2003, donc cette syntaxe était valide à
cette époque. Depuis, j'ai remplacé cela par l'équivalent en PHP.

<?
$rep = stristr ($HTTP_HOST, 'genealogie.com');
if ($rep == FALSE)
{ require ("./index_en.php"); }
else
{ require ("./index_fr.php"); }
?>


Denis
1 2 3