Vous pouvez exprimer ici vos remarques et suggestions sur la rapidité du moteur
WakkaFr.
Attention : j'ai fait une réorganisation sauvage de la page en essayant de ne trahir personne... --
CharlesNepote
Synthèse sur le problème des performances de WakkaFr
- La proposition de PatrickPaul est retenue par tous : avant de faire quoi que ce soit sur WakkaFr, pour les problèmes de performance, il nous rajouter quelques codes pour évaluer les performances (temps d'exécutions des pages php, des requêtes, etc...).
- Les MoteursDeTemplatesPhp intègrant un cache constituent une solution d'amélioration des performances ; cette solution n'est pas retenue à cause de la lourdeur de la mise en oeuvre ainsi que la nécessité d'apprendre le langage du moteur de templates.
- Nous sommes tous d'accord qu'il faut étudier un système de cache (et non forcément l'adopter : il faut que les résultats soient probants).
- Quelques références sur les techniques d'optimisation
Afin d'évaluer les gains : système de statistiques
Je suis sur le fait qu'il faut établir un système pour mesurer les temps d'exécution. Je propose même d'aller plus loin en développant un système qui créé des statistiques sur les temps d'exécutions. Cela coutera un peu mais ça permettra de mieux se rendre compte.
--
PatrickPaul
Il nous faut un moyen d'évaluer les gains. Que valent les informations de débogage mise en place par l'auteur ? Je crois me rappeler pour les avoir vues, qu'elles ne concernent que les requêtes SQL. --
CharlesNepote
Avant que
PatrickPaul ne lance son éditeur plus vite que son nombre ;-), je propose les idées suivantes.
Par expérience, tous les systèmes de statistiques qui sont codés dans une applications sont voués à l'échec et à de permanentes transformations : il y a toujours un utilisateur qui veut une chose que l'on a pas réalisé... "et pourquoi pas le ratio des "referrers" par mois et par pays" (je suis persuadé qu'il y a un gus qui va avoir ce besoin...).
Il y a donc une solution simplissime à ce problème : fournir des informations brutes au format CSV. De cette manière, l'utilisateur à tout loisir à traiter ces données comme il le souhaite, a posteriori, à l'aide de son outil statistique favori :
OpenOffice, Excell,
CristalReport?, etc. La richesse des traitements est donc déplacée dans les outils spécialisés et non dans l'application dont ce n'est pas le "coeur de métier". Ca n'empêchera d'ailleurs pas certains utilisateurs de créer des "actions" allant puiser dans ces données brutes.
Par ailleurs, les statistiques peuvent servir à autre chose qu'à évaluer les performances : il faut prendre le problème globalement.
Il nous faut donc déterminer maintenant (je vous laisse compléter) :
- les données que nous allons enregistrer
- date de la requête du client http
- heure-minute-seconde de la requête
- temps de traitement de la requête ?
- referrer de la requête
- adresse IP ou nom pleinement qualifié du client
- ...
- comment nous allons les enregistrer
- (L'enregistrement des ces données est optionnel (test d'un drapeau dans wakka.config.php))
- dans une table MySQL avec une ligne par enregistrement (au format CSV) ?
- dans une table MySQL avec un champ par donnée ?
- dans un fichier à plat avec une ligne par enregistrement (au format CSV) ?
- comment nous allons les restituer
--
CharlesNepote
Solution de cache
Pour le cache, je vais essayé de proposer quelque chose très bientôt, mais ça sera un gros morceau à realiser.
--
PatrickPaul
Pour le cache, je pense qu'il n'est peut-être pas nécessaire de réinventer la roue ; tu as vus les outils que je cite plus bas ? RFKcache me paraît pas mal... --
CharlesNepote
Pour ma part, je regarde un peu tous azimut (comme je suis débutant, je me forme un peu au passage). J'ai notamment regardé les solutions de cache php. Ce
message donne une explication intéressante sur les performances du php.
, un peu copurt, explique le principe des caches.
Encore un
comparatif des solutions de cache. Il y en a qui sont relativement faciles à mettre en place.
Une douzaine de classes de cache sont disponible sur
phpclasses.org.
J'en teste (ou projette d'en tester) actuellement quelques-uns.
- jpcache ne semble donner aucun résultat (mais je ne l'ai inclu que pour /wakka.php). jpcache est un peu trop simple et ne semble pas gérer l'annulation du cache d'une page donnée pour une action donnée. Les performances avaient pourtant l'air aléchantes.
- RFKcache est beaucoup plus poussé et permet notamment d'effacer une page particulière du cache (pas encore testé).
- morecache.
Cas d'utilisation du cache dans le cas d'une page non-interactive (ie : ne possédant d'appel { }).
- L'utilisateur modifie une page non-interactive.
- L'utilisateur "sauve" cette page non-interactive.
- Le système supprime du cache la page DerniersChangements.
- Le système met cette page en cache.
- L'utilisateur demande de visualiser cette page non-interactive.
- Le système propose la page du cache.
--
CharlesNepote
Je vais envisager un système de cache valable pour les pages interactives. A part les actions il y a aussi les inclusions raw qui pourraient être prises en compte, je pense que je ne les mettrais pas en cache, de façon à laisser le
FormatterRaw? le faire éventuellement (dans une prochaine version de
WikiNi bien sûr). --
LordFarquaad
Il y a dans la classe wakka une fonction
GetMicroTime?() pour mesurer le temps d'execution d'un bout de code.
--
DavidDelon
Mesure du temps de traitement
Avant les importants changements opérés par l'internationalisation et autres, je suggère d'améliorer la mesure du temps de traitement en démarrant le "chronométrage" en
tout début de traitement (soit au début de wakka.php) et en le terminant en
toute fin de traitement (c'est-à-dire à la fin de footer.php). Cela nous permettra de mesurer les écarts après la modification des divers éléments. En local chez moi, j'ai personnalisé
WakkaFr afin d'obtenir une mesure du temps global de traitement de chaque page affichée.
Pour cela, j'ai :
- modifié /wakka.php en ajoutant au tout début du fichier :
- list($g_usec, $g_sec) = explode(" ",microtime());
- define ("t_start", (float)$g_usec + (float)$g_sec);
- modifié /actions/footer.php en ajoutant en toute fin de fichier :
- list($g2_usec, $g2_sec) = explode(" ",microtime());
- define ("t_end", (float)$g2_usec + (float)$g2_sec);
- print "<span class=\"debug\">".round (t_end-t_start, 4)."</span>\n";
J'obtiens ainsi un résultat arrondit à la quatrième décimale (par exemple : 0.1532). Au passage j'observe chez moi en local des résultats oscillant entre 0.1 et 0.7 sur une machine pas trop chargée avec 256 Mo et un pentium III à 660 Mhz. Le code ci-dessus peut peut-être être amélioré...
Je propose que cette mesure soit systématiquement présente dans le source html à destination du client qui a demandé une page :
- soit affiché
- soit avec l'attribut CSS display: none qui l'empeche de s'afficher mais le laisse présent dans le source de la page.
Il est cependant probable que la présence systématique de cette mesure empêche l'utilisation du cache (je ne comprend toujours pas bien comment fonctionne le cache). Aussi il serait peut-être plus intéressant de proposer cette mesure comme une option (configurable à travers le fichier de configuration).
Qu'en pensez-vous ?
--
CharlesNepote
A mon avis, on peut d'ores et déjà mettre en place la mesure proposée par
CharlesNepote. Pourquoi ne pas ajouter l'affichage, pour l'instant, dans le paragraphe debug existant de footer.php ?
--
DavidDelon
D'accord avec Patrick et David. Reste deux questions en suspend :
- Comment afficher le temps total d'exécution que j'ai proposé :
- dans le groupe de mots (<span>) de style intra paragraphe "debug" existant, affiché en fonction du paramètre "debug"
- dans un groupe de mots (<span>) de style intra paragraphe "debug" à part, affiché en fonction du paramètre "debug"
- dans un groupe de mots (<span>) de style intra paragraphe "debug" à part, affiché en fonction du paramètre "print_time"
- dans un paragraphe (<div>) de style "p_debug", affiché en fonction du paramètre "debug" (Pour : on peut placer le paragraphe n'importe où (par exemple en haut à gauche) uniquement en modifiant la feuille de style)
- dans un paragraphe (<div>) de style "p_debug", affiché en fonction du paramètre "print_time"
- Quels sont les fonctions proposées par le système de statistiques évoqué par Patrick ? (je vous laisse remplir un peu ;-)
Pour la question 1 je penche plutôt pour la solution 5 car je pense qu'il y a des administrateurs techniques ou fonctionnels qui seraient désireux de voir systématiquement le temps d'exécution de la page sans avoir toutes les informations de débogage (par exemple ici sur
WakkaFr où il me paraît intéressant d'avoir systématiquement cette information (pour cause d'observation du comportement des nouvelles versions) sans avoir néanmoins les informations de débogage). --
CharlesNepote OK --
DavidDelon
Bon j'ai choisi finalement l'option 1. On verra ensuite pour la 5...
J'ai ajouté en plus : l'arrondi à la 4ème décimale de toutes les mesures ; le temps total des requêtes SQL ; le % de requêtes SQL sur le temps total (au passage, chez moi j'obtien entre 15 et 30 % max). On verra le code ci-dessous de /actions/footer.php. Mais je ne peux plus rien publier sur le CVS !...
Est-ce que vous voyez d'autres données statistiques que l'on pourrait intégrer facilement ?
--
CharlesNepote
<?php
if ($this->GetConfigValue("debug"))
{
print "<span class=\"debug\"><b>Query log :</b><br />\n";
foreach ($this->queryLog as $query)
{
print $query["query"]." (".round($query["time"], 4)." s)<br />\n";
$t_SQL = $t_SQL + $query["time"];
}
print "</span>\n";
print "<span class=\"debug\">".round($t_SQL, 4)." s (total SQL time)</span><br />\n";
list($g2_usec, $g2_sec) = explode(" ",microtime());
define ("t_end", (float)$g2_usec + (float)$g2_sec);
print "<span class=\"debug\"><b>".round(t_end-t_start, 4)." s (total time)</b></span><br />\n";
print "<span class=\"debug\">SQL time represent : ".round((($t_SQL/(t_end-t_start))*100),2)."% of total time</span>\n";
}
?>
En cherchant du côté des profiler pour php j'ai trouvé ceci :
dbg qui est un debugger + profiler. Très facile à installer, on peut s'en servir juste pour la mesure des temps d'execution en suivant l'exemple
Sample of using dbg/profiler API in PHP à télécharger sur le site de dbg (partie download).
Pour avoir une idée de ce que ça donne, voici quelques lignes de résultat (voir ci-après) . Yapluka analyser tout ça ...
Et ca donne ceci (je n'ai gardé que les 10 fonctions les plus consommatrices de temps), sur une page
standard, sans appel d'action, du type page principale.
Fichier | Total ms | Nbre appel | Fonction |
/wakka.php | 7,291 | 16 | wiki:loadpage |
/wakka.php | 8,074 | 20 | wiki::href |
/actions.footer,php | 8,155 | 18 | ::main |
/wakka.php | 10,361 | 16 | wiki::loadall |
/wakka.php | 10,426 | 1 | ::main |
/wakka.php | 12,500 | 15 | wiki::link |
/wakka.php | 30,067 | 37 | wiki::getmicrotime |
/formatters/wakka.php | 76,977 | 24 | wakka2callback |
/wakka.php | 105,612 | 18 | wiki::query |
/wakka.php | 184,813 | 7 | wiki::includebuffered |
Total (toutes fonctions) :615,705
Sans surprise, les query consomment beaucoup, mais, surprise, les includebuffered également (c'est juste
le "include" qui est comptabilisé; ce temps d'inclusion n'étant pas constant, je suppose qu'il est fonction de la taille du
fichier inclus ...
Certes la structure de l'application est trés modulaire mais ça se paie donc quelque part ...
A noter au passage : le temps consommé par getmicrotime !
Une petite erreur d'analyse : j'ai fait ces tests sur un wakka sans la lecture du fichier interwiki. avec la lecture de interwiki
on peut rajouter en moyenne 50 ms. Je propose de supprimer ce fichier de l'application, son interêt ne me parait pas franchement évident.
--
DavidDelon
Bravo David pour cette analyse. Mes questions/réflexions un peu dans le désordre.
- Pourquoi IncludeBuffered? est-il appelé 7 fois ça me paraît beaucoup ?... N'y a-t-il pas des choses qu'on peut réintégrer dans wakka.php (décisions à ne pas prendre à la légère) ? ;
- Pour les Query : cf. ma proposition de les regrouper : je ne sais si c'est possible. J'ai tout de même noté que nombre d'entre eux ont une structure très proche.
- Si le drapeau "debug" n'est pas positionné, getmicrotime est donc appelé ((query*2) + 1) fois pour rien !... pourquoi au moins ne pas faire un test dans getmicrotime ou dans query : if ($this->GetConfigValue?("debug")) ? Si je calcule bien, on peu gagner environ 4-5% de performance (30 ms sur 615 ms).
- Ce serait intéressant de réutiliser l'ancien Wakka pour voir s'il y a des différences.
- Imaginons qu'on puisse gagner :
- peut-être 30 ms pour le getmicrotime
- peut-être 50 ms pour les query (soyons très optimistes)
- peut-être 70 ms pour les include
- soit, en tout 150 ms sur 615 ms (soit environ 25%), c'est de la pisse de rat en comparaison des délais réseau sur free... (cf. mes chiffres plus bas)
- On gagnera éventuellement un peu en intranet ou sur d'autres serveurs que free, sur des pages très complexes.
Les problèmes de performances que nous avons ne sont donc pas côté applicatif. On peut donc, par exemple, se demander si on a bien gagné d'externaliser la feuille de style : en théorie oui parce qu'on utilise le cache du navigateur, mais en pratique, il faut une requête réseau supplémentaire pour être sûr que la page n'a pas changé. Ce qu'il faut donc voir c'est étudier si l'on peut
.
--
CharlesNepote
module |
line |
hits |
time/hit, ms |
total time, ms |
min time, ms |
max time, ms |
context ID |
context |
/var/www/wakkatest/wakka.php |
11 |
1 |
0.781 |
0.781 |
0.781 |
0.781 |
77 |
::main |
/var/www/wakkatest/wakka.php |
14 |
1 |
0.995 |
0.995 |
0.995 |
0.995 |
77 |
::main |
/var/www/wakkatest/wakka.php |
15 |
1 |
0.522 |
0.522 |
0.522 |
0.522 |
77 |
::main |
/var/www/wakkatest/wakka.php |
19 |
1 |
0.008 |
0.008 |
0.008 |
0.008 |
77 |
::main |
/var/www/wakkatest/wakka.php |
31 |
1 |
0.066 |
0.066 |
0.066 |
0.066 |
1 |
wiki::wiki |
/var/www/wakkatest/wakka.php |
32 |
1 |
26.597 |
26.597 |
26.597 |
26.597 |
1 |
wiki::wiki |
/var/www/wakkatest/wakka.php |
36 |
1 |
2.657 |
2.657 |
2.657 |
2.657 |
1 |
wiki::wiki |
/var/www/wakkatest/wakka.php |
37 |
1 |
0.152 |
0.152 |
0.152 |
0.152 |
1 |
wiki::wiki |
/var/www/wakkatest/wakka.php |
38 |
1 |
0.091 |
0.091 |
0.091 |
0.091 |
1 |
wiki::wiki |
/var/www/wakkatest/wakka.php |
43 |
16 |
0.113 |
1.807 |
0.092 |
0.197 |
2 |
wiki::query |
/var/www/wakkatest/wakka.php |
44 |
16 |
7.085 |
113.366 |
4.100 |
17.079 |
2 |
wiki::query |
/var/www/wakkatest/wakka.php |
49 |
16 |
0.199 |
3.176 |
0.191 |
0.204 |
2 |
wiki::query |
/var/www/wakkatest/wakka.php |
51 |
16 |
0.130 |
2.084 |
0.104 |
0.185 |
2 |
wiki::query |
/var/www/wakkatest/wakka.php |
53 |
16 |
0.095 |
1.520 |
0.080 |
0.155 |
2 |
wiki::query |
/var/www/wakkatest/wakka.php |
55 |
17 |
0.182 |
3.100 |
0.110 |
0.224 |
3 |
wiki::loadsingle |
/var/www/wakkatest/wakka.php |
58 |
16 |
0.157 |
2.508 |
0.139 |
0.175 |
4 |
wiki::loadall |
/var/www/wakkatest/wakka.php |
60 |
16 |
0.703 |
11.249 |
0.197 |
1.928 |
4 |
wiki::loadall |
/var/www/wakkatest/wakka.php |
61 |
16 |
0.218 |
3.482 |
0.180 |
0.511 |
4 |
wiki::loadall |
/var/www/wakkatest/wakka.php |
63 |
16 |
0.181 |
2.896 |
0.127 |
0.196 |
4 |
wiki::loadall |
/var/www/wakkatest/wakka.php |
68 |
33 |
0.805 |
26.568 |
0.719 |
0.897 |
5 |
wiki::getmicrotime |
/var/www/wakkatest/wakka.php |
71 |
7 |
0.153 |
1.070 |
0.075 |
0.269 |
6 |
wiki::includebuffered |
/var/www/wakkatest/wakka.php |
74 |
7 |
0.117 |
0.816 |
0.098 |
0.137 |
6 |
wiki::includebuffered |
/var/www/wakkatest/wakka.php |
76 |
7 |
0.045 |
0.316 |
0.016 |
0.093 |
6 |
wiki::includebuffered |
/var/www/wakkatest/wakka.php |
77 |
7 |
0.053 |
0.373 |
0.047 |
0.067 |
6 |
wiki::includebuffered |
/var/www/wakkatest/wakka.php |
78 |
7 |
0.266 |
1.860 |
0.189 |
0.298 |
6 |
wiki::includebuffered |
/var/www/wakkatest/wakka.php |
80 |
7 |
0.212 |
1.486 |
0.112 |
0.353 |
6 |
wiki::includebuffered |
WakkaFr ça rame le soir et le week-end (sur free en tous cas)
Alors voila, moi mon Wakka fonctionne sur Free, comme ton site David, et y'a des heures où ça rame à mort... et ça vient des la base de données
MySQL. Je veux proposer une projet "
WakkaFr=>HTML" qui permettrait de créer de façon automatique une version html de toutes le pages, pour que les visiteurs puissent tout le temps bénéficier d'une bonne vitesse d'accès au site au moins en lecture.
Qu'en dites-vous ? Personnellement je pense pas que ça soit trop difficile à mettre en oeuvre. --
PatrickPaul
C'est vrai que ça rame, si ça devient trop pénible il y a peut etre moyen de transferer tout ça vers une autre machine ... D'un autre côté, ça nous "oblige" à faire du performant !
Sinon pour ton idée : c'est bien de "cache" dont tu veux parler ? Pas de problème, d'ailleurs l'auteur de wakka en parle dans son site, à mon avis c'est pas si simple, il faut bien
veiller par exemple à regenerer une page cachée faisant référence a une page en attente de création (une wantedpage) lors de la création de cette page.
--
DavidDelon
- Question au passage : comment savez-vous que les lenteurs viennent du SQL et pas du traitement PHP ou des deux ?...
- -- CharlesNepote
- Réponse : Eh bien j'ai eu des messages direct d'erreur sql comme quoi la base de données n'était pas acessible. Deuxièmement, j'ai un autre site qui n'utilise pas de bases de données et qui marche toujours très rapidement sur free.... Je vous laisses conclure...
- -- PatrickPaul
- On va pouvoir réellement être fixés avec le % de traitement SQL sur le temps total que je propose -- CharlesNepote.
- Bilan des courses : des mesures effectuées samedi 30/11/2002 à 15:00, classée dans l'ordre de délai croissant de fin d'affichage dans Mozilla (je précise qu'aucun autre processus gourmand ne tourne sur ma machine en dehors du navigateur).
- Exemple 1 :
- 0.1457 s (total SQL time)
- 0.2333 s (total time)
- SQL time represent : 62.47% of total time
- Document: Done 1.051 s
- Exemple 2 :
- 0.275 s (total SQL time)
- 1.3404 s (total time)
- SQL time represent : 20.52% of total time
- Document: Done 2.433 s
- Exemple 3 :
- 0.0141 s (total SQL time)
- 0.0597 s (total time)
- SQL time represent : 23.7% of total time
- Document: Done 11.066
- Exemple 4 :
- 0.0132 s (total SQL time)
- 0.1443 s (total time)
- SQL time represent : 9.16% of total time
- Document: Done 25.917 s
- 1ère conclusion : le délai d'affichage des pages n'est pas proportionnel au temps de traitement SQL.
- 2ème conclusion : le délai d'affichage des pages n'est pas proportionnel au temps de traitement total.
- 3ème conclusion : le temps de traitement total dépasse très rarement la seconde.
- 4ème et dernière conclusion : on aurra beau faire une application hyper optimisée (cache, optimisation SQL, etc.) ça ramera toujours autant sur free.
- Ce que je voudrais bien savoir, c'est où le bât blesse sur free : réseau ? bande passante ? etc.
(Oui : le temps de resolution DNS, la latence (temps de reaction materiel reseau), le debit disponible, la charge de la machine serveur (la prise en charge de la requête par le serveur ne sera pas immédiate) ... --
DavidDelon )
- Charles, mon avis est tout à fait différent du tient. Je ne pense pas du tout que ça ramera toujours sur Free. Au contraire, j'espère arriver à rendre le moteur très rapide même sur Free. STP ne t'emballes pas avec tous les trucs de cache dont tu as parlé. A mon avis tu pourras faire tout ce que tu voudras de ce côté là ça ramera toujours. Au fait je sais pas si David t'en a parlé mais on aimerai bien un nouveau look pour le site.
- -- PatrickPaul
Patrick, avant toute modification importante de wakka pour mettre en place les caches, j'aimerais que toi non plus tu ne t'emballes pas
avec une solution qui risque de bouleverser totalement la structure de l'application, aussi je te demande de ne pas modifier le CVS pour tout
ce qui est cache mais de nous montrer ce que ca donne sur ton site sur free avant, comme
CharlesNepote et moi-même l'avont fait pour l'internationalisation ou sur d'autres sujets.
--
DavidDelon
- D'accord avec David. Pour répondre à Patrick : je conçois bien que ton avis soit différent. Peux-tu argumenter ?
- -- CharlesNepote
- 1. Je ne m'emballe pas.
- 2. Je ne compte pas du tout changer la structure de l'application. Au contraire je ne vais pas toucher aux fichiers existant je pense.
- 3. Je vous montrerai ce que ça donne avant, pas de problème.
- 4. Pour répondre à Charles, j'adore argumenter mais je suis plutôt un orateur :-P J'essyerai cependant de faire des efforts.
- -- PatrickPaul
- 1. J'ai un copain qui a monté récemment un wiki en ASP et qui l'a publié sur internet. Il utilise les méthodes de caches clients que je suggère dans GererLesCachesAuNiveauApplicatif. Je vous suggère d'aller voir son site http://www27.brinkster.com/bleuciel/ et de faire le test suivant : cliquez sur WikiEnAsp?, puis sur Wiki2HTML? (la page est un peu longue à charger), puis cliquez sur Accueil et refaire le chemin WikiEnAsp?, puis Wiki2HTML? : vous verrez que les pages WikiEnAsp? et Wiki2HTML? ne sont pas redemandées au serveur mais prise dans le cache du navigateur. Si l'une de ces deux pages est modifiée, elle sera alors redemandée au serveur. La plupart des navigateurs devraient gérer cela correctement. Cette méthode requiert trois bouts de code (je publierai les exemples plus tard ; mes tests en local sont concluants pour wakkafr). Cette solution ne résoud pas tous les problèmes mais elle est particulièrement simple à mettre en oeuvre et offre des gains de performance immédiats. -- CharlesNepote ;Je viens de jeter un coup d'oeil, c'est clairement quelque chose à mettre en place immédiatemment -- DavidDelon
- 2. Pourquoi je pense que les caches de page réalisés en php seront peu efficaces ? Car je pense que, sur free, c'est le réseau qui bouffe du temps, pas les traitements. Je n'ai pas encore fait le test (d'où je suis je ne peux pas), mais je vais ce soir enregistrer une page de wakkafr au format HTML, l'inclure dans un php qui fera juste <?php include xxx.html ?> et mesurer le délai donné par Mozilla (délai calculé depuis le clic jusqu'à l'affichage total de la page). Je pense que je vais obtenir très peu de différence entre la page générée par wakkafr et la page générée par l'include. Rendez-vous ce soir.
- 3. Les systèmes de cache peuvent avoir une utilité en intranet, sur de petits serveurs, avec des pages très complèxes. Et je pense qu'on peut quand même les étudier.
- 4. (Moi j'aime bien la diversité et on est pas tous obligé d'avoir les mêmes idées, les mêmes angles d'approches d'un problème, les mêmes qualités et défauts. L'important c'est de pouvoir parler.)
- -- CharlesNepote
- 1. Super idée le cache en local.
- 2. Pour ce qui est des pages sur Free, personnellement j'ai un site html et un site avec WakkaFr installé et il n'y a pas photo : le site en html s'affiche quasi instantannément alors que Wiki, même si ça peut être rapide à certaine heures, est bien plus lent. De toute façon il serait bon d'éviter tous ces appels à la base de données je pense.
- 3. Moi aussi j'aime bien la diversité et j'encourage même à ce qu'on développe plusieurs solutions et, pourquoi pas, au final en choisir une ou bien un mélange de plusieurs solutions.
- 4. A ce soir donc. Je serais sur le chat de 20h à 21h environ.
- - PatrickPaul
- 1. Me too
- 2. J'ai aussi des sites en html sous free et ca rame parfois autant que wakka. Mais je suis d'accord pour qu'on etudie un système de cache.
- 3. On peut imaginer un CVS avec trois branches : stable , test et prospective.
- 4. J'essairai d'être là.
- - DavidDelon
- J'ai donc effectué mes tests ce soir comme je l'avais proposé tout à l'heure. Résultat des courses, vous allez pouvoir comparer vous-même :
- http://charles.nepote.free.fr/wakkafr/wakka.php?wiki=BacASable : la page générée par le moteur wakkafr
- http://charles.nepote.free.fr/wakkafr/index2.php : la page générée par le code suivant :
- <?php
- list($g_usec, $g_sec) = explode(" ",microtime());
- define ("t_start", (float)$g_usec + (float)$g_sec);
- include "index2.html";
- list($g2_usec, $g2_sec) = explode(" ",microtime());
- define ("t_end", (float)$g2_usec + (float)$g2_sec);
- print "\n\n<br /><br /><b>".round(t_end-t_start, 4)." s (total time)</b></span><br />\n";
- ?>
- (sachant que index2.html est un enregistrement de la page générée par le moteur wakkafr.
- Bilan des courses à 21 h 20 :
- de 3.5 à 11 s avec une moyenne pifométrique de 5-6 sur une douzaine d'essais pour 1 (avec un pic à 35 s. que je ne compte pas)
- de 1.7 à 3.8 s avec une moyenne pifométrique de 3 sur une douzaine d'essais pour 2 (avec un pic à 12 s. que je ne compte pas)
- Les 2-3 secondes de différences s'expliquent en grande partie par le temps de traitement. Mais, il faut bien voir que la page est particulièrement lourde et qu'un délai de d'affichage de 3 s. pour une telle page où on trouve seulement 1 include, n'est pas normal.
- Conclusion provisoire :
- oui, un cache php côté serveur peut améliorer les délais sur des pages complexes ;
- non, il ne faut pas s'attendre à avoir des résultats miracles sur free.fr ; il vaut donc mieux exploiter aussi au mieux les caches des navigateurs.
- -- CharlesNepote
Regrouper les requêtes SQL
Actuellement (30/11/2002), chaque page demande beaucoup de requêtes SQL dissociées :
- des requêtes pour évaluer le propriétaire de la page
- autant de requêtes SQL qu'il y a de liens dans la pages
- 1 fois sur trois, deux requêtes SQL pour la maintenance des bases
- etc.
Ces requêtes SQL, du fait qu'elles soient dissociées, coûtent du temps réseau et du temps de traitement.
Il serait intéressant d'évaluer s'il est possible d'en regrouper certaines.
--
CharlesNepote
Ne pas faire de requêtes quand ça n'est pas nécessaire
[copier/coller sauvage depuis wakkawiki.com par
CharlesNepote]
i done some measurements of the time the SQL queries take and conclude that they are not the greatest problem regarding the page rendering speed. of course one could (should?) tweak at the link function, which makes often unnecessary queries or introduce a new function that don´t do a query. a very good example is my own
PageIndexAction? which uses the link-function to print all the page links which of course
are WikiWords? and existing pages.
// it is known that $tag is a valid tag
function ComposeLinkToPage($tag, $method = "", $text = "", $track = 1) {
if (!$text) $text = $tag;
$text = htmlentities($text);
if ($_SESSION["linktracking"] && $track) $this->TrackLinkTo($tag);
return '<a href="'.$this->href($method, $tag).'">'.$text.'</a>';
}
--
ErusUmbrae
J'ai fait quelques tests de regroupement de requete pour l'affichage des liens wiki.
Le principe que j'ai retenu est le suivant : plutôt que d'aller vérifier l'existence de chaque
MotWiki parmi la liste des pages créées, avec, à chaque fois une requête différente, faire une seule requête pour aller chercher la liste de l'ensemble des pages du wiki, garder cette liste en mémoire, et s'y référer pour chaque lien.
J'ai constaté un gain significatif en temps d'execution :
Query log :
select * from wakkafr_pages where tag = 'PagePrincipale' and latest = 'Y' limit 1 (0.0031)
select distinct tag from wakkafr_pages where latest = 'Y' order by tag (0.0125)
select * from wakkafr_acls where page_tag = 'PagePrincipale' and privilege = 'read' limit 1 (0.0018)
select * from wakkafr_pages where comment_on = 'PagePrincipale' and latest = 'Y' order by time (0.0048)
select * from wakkafr_acls where page_tag = 'PagePrincipale' and privilege = 'write' limit 1 (0.0016)
0.0239 s (total SQL time)
0.3218 s (total time)
SQL time represent : 7.43% of total time
--
DavidDelon
(Si tout le monde est d'accord, je mets à jour le CVS).
Question 1.
Est-ce que ça ne va pas pénaliser les performances dans le cas d'un très gros wiki ; par exemple 20 ou 30 000 pages ? Je ne comprends pas bien ce qui est fait actuellement... pour chaque mot wiki une requête va chercher les noms de chaque page de la base et regarde pour chaque chaîne ramené si elle correspond au mot wiki ? C'est ça ? Donc on garde aussi en mémoire (certe pas dans une variable) la liste des noms des pages ?
[Tu as bien compris, c'est l'inconvénient de la solution pour un gros wiki, entre temps je pense avoir trouvé une solution plus acceptable :
charcher en mémoire la liste des pages présentes dans le wiki
et faisant partie des liens sortants de la page (table links). --
DavidDelon]
Question 2.
Il semble en effet que le pourcentage du temps SQL a baissé. Est-ce régulier sur plusieurs requêtes. A contrario, le % du temps de requête SQL a pu baisser, mais le temps total a pu augmenter ?
[Le % a bien baissé, je n'ai pas donné le détail de l'execution rendu par le debugger mais il y a une baisse significative du temps passé dans query sans augmentation du temps total --
DavidDelon]
Si tu es sûr de tes mesures je suis évidemment totalement d'accord pour l'intégrer au CVS.
Il me semble aussi que la solution d'
ErusUmbrae est intéressante dans le cas où on est sûr que les pages existent.
[Oui --
DavidDelon]
--
CharlesNepote
Les tests sur ma dernière proposition ne sont pas satisfaisant (liste des pages présentes dans le wiki
et faisant partie des liens sortants de la page), d'un autre côté le fait de charger l'ensemble des pages du wiki ne me parait pas si judicieuse : c'est un peu trop grossier,
comme le fait remarquer
CharlesNepote : pour un gros wiki cela risque d'être pénalisant. Je cherche autre chose.
Conclusion : j'applique la proposition de
ErusUmbrae à l'ensemble du projet : creation de la fonction ComposeLinkToPage dans wakka.php
et utilisation systématique quand on est sûr que le lien est une page existante.
--
DavidDelon
Quelques références sur les techniques d'optimisation
- phpLens: A HOWTO on Optimizing PHP with tips and methodologies [en] : l'optimisation d'une application php ne passe pas que par l'optimisation du code mais aussi par une bonne connaissance de l'environnement d'execution afin d'identifier les goulets d'étranglement. Résumé des optimisations proposées (par ordre d'importance décroissante)
- Compréhension de l'environnement : Apache, IIS, base de données, OS, réseau, hardware ... pour pouvoir optimiser au mieux.
- Une CPU supplémentaire est plus importante que de la RAM.
- Option de compilation de php (configure -enable-inline-optimization)
- Optimisation base de donnée (index, requêtes ...)
- Cache HTML pour les pages changeant peu frequemment
- Faire des mesures du code et tester la montée en charge le plus tôt possible.
- Envisager l'utilisation de l'"opcode cache" (compilation php).
- Utiliser ob_start() (et ob_gzhandler)
- Envisager l'utilisation de Zend optimiser (gratuit)
- Optimiser le code php :
- boucle (invariant en dehors)
- utiliser les fonctions sur tableaux et chaines de caractères
- préferer les fonctions strXXX(), puis pregXXX() puis eregXXX() pour les recherches et remplacements
- unset() les variables non utilisées
- foreach() pour lire les tableaux
- echo au lieu de print (mais privilegier ob_start())
- utiliser les methodes de classes dérivées, quand c'est posssible
- ...
--
DavidDelon
Un outil pour optimiser le code PHP
J'ai trouvé un debugger PHP qui possède une fonction de profiler assez interressante. Les données du profiler sont "brute" mais exploitable. Il s'agit de XDebug (
http://www.xdebug.org ).
--
GarfieldFr
Optimisation requetes SQL
Je travaille depuis quelque temps sur le moteur de Wikini pour faire quelques adaptations (voir
GoubsIntegrationSpawEditeur ) et comme l'a dit
DavidDelon il y a beaucoup de requetes Sql générées. Sur mon site, qui utilise un menu sur la partie droite, il y a en moyenne 30 requetes Sql par page. Cela est du essentielement aux mots Wiki. Si il y a peu d'utilisateurs sur le site cela ne pose pas de problème et sur mon site perso les tps de réponse reste tres rapides. Mais pour un site avec de nombreux utilisateurs on risque d'arriver à des tps de réponse tres long (
si 100 utilisateurs demandaient une page en meme tps cela ferait environ 3 000 requetes SQL à traiter. Le moteur Sql ne traitant qu'une requete à la fois il y en a qui risque d'attendre un peu !)
La solution de charger tous les
tag des pages en mémoire pourrait fonctionner sur un site avec peu de pages mais risquerait de n'être pas viable si le nb de pages est conséquent.
Une autre solution consisterait peut être à mettre dans un tableau tous les mots Wiki de la page, puis de construire une requete Sql à partir de ce tableau (
... WHERE tag = 'motWiki1' OR tag = 'motWiki2 ...). Le résultat de cette requete permettant ensuite de construire un tableau du type : tab_tag_ok('tag1') = true. Au moment du "formatage" de la page il ne reste plus qu'a tester pour chaque motWiki la valeur de ce tableau (
if (tab_tag_ok(motWiki1)) Alors définir le lien Sinon mettre un lien avec "?" pour permettre la création de la page).
Que pensez vous de cette proposition ? il n'y a plus qu'une seule requete pour gérer les mots Wiki !
--
GouBs
Interessant, mais pour mettre dans un tableau tous les mots Wiki d'une page, il faut parcourir celle-ci une première fois. Il faut donc mesurer (ou évaluer) si ce parcours supplémentaire n'est pas plus consommateur en temps (a vue de nez, je dirais qu'il y a globalement gain de temps). Je soutiens cette proposition. --
DavidDelon
Comme
DavidDelon, à vu de nez cela semble plus rapide mais il faudrait voir à partir de quel nombre de
MotWiki le moteur fait un
fullscan de la table pages au lieu d'utiliser l'index. En effet, exécuter 10 requêtes recherchant une seule page peut être plus rapide que d'executer une seule requête recherchant 10 pages, tous dépend de la manière dont est executée la requête par le moteur et notament si il fait un
fullscan de la table dans le 2eme cas ou pas. Par contre, pour optimiser le SQL actuel, il faudrait voir s'il est possible de faire une préparation des requêtes puis de les utiliser simplement avec un paramètre (je ne sais pas si
MySQL peu faire ca) --
GarfieldFr
Je ne connais pas assez
MySQL pour savoir si le moteur fait un
fullscan de la table ou utilise l'index. J'ai fait la modif sur mon site et les résultats sont concluants : gain tps total environ 15% les requetes SQL passent d'une moyenne de 30 à 10 et le pourcentage consacré au requetes passe de 33% à 22% (environ). Mesures faites sur mon site. Le problème est que sur mon site il n'y a qu'environ 70 pages (valides) et 750 enregistrement dans la table
page. Il faudrait faire des essais sur un site + gros.
Toutes les modifications sont incluses dans la class wiki.J'ai donné des détails et le code source sur la page
OptimisationSql. --
GouBs
Demande à
DavidDelon un dump de la base de
WikiNi, la tu aura à peu près ... beaucoup de pages pour faire des tests --
GarfieldFr
Pour ma part, je pense que
GouBs pourrait encore optimiser son code en profitant de l'idée suggérée par
DavidDelon plus haut dans cette page : utiliser la table
wikini_links. En effet, quand on affiche une page on utilise sa dernière version dans la base qui a déjà été analysée au moment de son enregistrement, donc les liens qui la concernent dans la table
wikini_links sont à jour et on peut les utiliser. Partant de ce constat, on peut obtenir très rapidement la liste des
MotWiki d'une page sans avoir besoin de la recalculer. On peut donc aussi facilement tester leur présence dans la base, mais la je dis attention : il faut s'assurer que la taille de la requête reste raisonnable car je suis presque certain qu'il y a une limite aux nombres de caractères que l'on peut envoyer... Il faudrait vérifier cette limite et découper en plusieurs requêtes le cas échéant. --
ProgFou
L'idée de
ProgFou est interressante et je vais creuser dans cette direction. Pour le nombre de caractères dans une requete que l'on peu envoyer il y a surement une limite mais je ne pense pas qu'elle soit pénalisante. A titre d'information j'utilise sur mon site une action calendrier que j'ai développée. J'affiche actuellement 4 mois et comme chaque jour est considéré comme une page j'ai plus de 160 pages (avec les autres éléments) à vérifier la présence. Tout se passe sans problème le temps de traitement est biensur plus long pour cette page et se situe au environ de 1.2sec. La part SQL est elle négligable (3%). L'idée exprimée juste au dessus me permettra peut être d'optimiser le traitement (ne pas faire deux "format" de la page) --
GoubS
- Je pensais plus à une limite technique dans le sens taille maximale de la chaîne que l'on peut fournir à la fonction mysql_query(). Si la limite est de 1024 caractères (au hasard) et que la chaîne envoyée dépasse cette limite, cela posera un problème fonctionnel (la requête sera refusée), voir même éventuellement des problèmes de sécurité. À étudier sérieusement donc. -- ProgFou
- Après quelques recherche sur le net j'ai trouvé ceci "La taille totale d'une chaine de requete est limitée par la variable max_allowed_packet (utiliser la commande show variables pour obtenir sa valeur). La taille de cette variable est de 1MO par défaut, mais peut être augmentée (jusqu'à 15Mo pour la version 3.23). De manière interne, MySQL peut gérer des constantes de type chaines dans les clauses WHERE aussi grandes que la taille des champs TEXT et BLOB. Il est possible d'avoir 85 000 éléments dans une clause WHERE, et les parenthèses peuvent être imbriquées sur 1 200 niveaux." Il semble donc que la taille de la requete ne soit pas une limite dans le cas de notre applicatif. (source de l'info) --GoubS
- On a effectivement de la marge... :) Parfait. -- ProgFou
Optimisation de l'utilisation de la base de données
Actuellement,
WikiNi est assez lourd au niveau de la base de données. Une page moyenne prend facilement 10 à 20kio. Chaque version est une sauvegarde complète de cette page, ce qui signifie qu'il faut multiplier la taille de la page par le nombre de versions pour obtenir une aproximation de la taille prise. Actuellement, la seule chose qui est faite pour éviter de faire trop gonfler la base de données est la purge, mais si on considère que chaque page a en moyenne 5 révisions au cours des 90 derniers jours, et qu'un wiki moyen a minimum 100pages, cela fait déjà plus de 5 à 10mio. (tous ces chiffres ne sont que des estimations...) Cela peut vraiment poser problème à certains, beaucoup d'hébergeurs bon marché (ou gratuits) ne proposant pas plus de 50 à 100mio, et beaucoup moins pour la base de données (ou alors vous mettent sur un serveur plus lent si votre base de données dépasse les Xmio, c'est ce que fait par exemple OVH à partir de 15mio...) : si la personne veut mettre en ligne plusieurs
WikiNi, ou même d'autres sites, le quota sera vite dépassé...
Je propose donc d'envisager différentes possibilités pour réduire la taille de la base de données (sans perdre pour autant des informations)
- Restauration d'une ancienne version: actuellement quand on restaure une version antérieure d'une page, on crée en fait une nouvelle révision, donc on resauve entièrement la page alors qu'en fait il n'y a aucun changement. Il serait préférable de modifier simplement le champ latest dans la table pages...
- Les champs body et tag de la table pages est indexé (en FULLTEXT), conséquences: cette table prend environ deux fois plus de place et les insertions sont plus lentes. Ceci ne sert, je pense, que pour l'ActionTextSearch (qui fonctionne actuellement en et a donc obligatoirement besoin d'un FULLTEXT). Si on la remplace par l'ActionNewTextSearch, cet index pourra donc normalement être supprimé (ALTER TABLE `wikini_pages` DROP INDEX tag)
- Il arrive souvent de faire une révision juste pour corriger une faute d'orthographe ou juste quelques lignes, mais la page est complètement resauvée... Il serait peut-être bon d'envisager un système de sauvegardes par "diffs":
- Au moment de sauvegarder une page:
- Toutes les X versions, on fait une sauvegarde complète de la page
- Sinon un système de comparaison de type diff compare la dernière version complète de la page avec la nouvelle version:
- S'il y a beaucoup (à définir) de différences, on refait une sauvegarde complète
- "beaucoup" pourrait simplement être le cas où le diff prendrait plus de place que la page complète
- S'il y a peu de différences, on enrégistre juste le diff
- (on pourrait comparer cela au format de compression divx en fait)
- Au moment d'afficher une page, on charge la dernière version (qui serait toujours celle avec latest = 'Y') et la dernière version complète (qui doit donc pouvoir être identifiée par une simple condition dans la requête SQL !). La clause ORDER BY devrait permettre d'avoir, par exemple, la version complète comme premier enrégistrement et le diff comme second.
- Si on n'obtient qu'un seul enrégistrement, ce doit être la version complète (il faudrait modifier le système de purge pour qu'il ne supprime pas la dernière version complète !)
- Si on obtient deux enrégistrements, alors il suffit de reconsituter la version actuelle à partir de ceux-ci
- Il faudrait refaire le handler diff: fonctionnement très facile quand l'ancienne version est la dernière version complète, mais quand ce n'est pas le cas, c'est une autre histoire...
--
LordFarquaad
- Euh, question de néophite : pourquoi faudrait-il sauvegarder la page entièrement pour des grosses modifs ou toutes les x versions, c'est dangereux de n'enregistrer que les différences ? En tout cas ça parait logique de ne pas réenregistrer à chaque fois toute la page. NoooZ
- Pourtant actuellement la page est "réenrégistrée" à chaque fois... Je pense qu'il est tout de même bon de faire une sauvegarde complète de temps en temps pour éviter de potentiels problèmes de corruption à cause de diff, ou de pertes de données... -- LordFarquaad
ProgFouASuivre
Remarques en vrac
Mon expérience sur SPIP m'amène à faire quelques remarques diverses...
- Pour mesurer le temps d'exécution global d'une page, microtime() n'est pas bon car il omet les temps de parsing du code PHP. Il faut utiliser un utilitaire externe comme
ApacheBench? (/usr/sbin/ab, sur tout serveur Apache) ; cet outil doit être lancé en local sur le serveur.
- Sur une machine "typique" (1-2 GHz), parser 1 Ko de code PHP prend en ordre de grandeur 1 ms (donc 100 ko = 100 ms, rien que pour parser le code, pas l'exécuter). Exception cependant pour le code HTML hors des "<?php ... ?>".
- Sur du code "typique", les lenteurs se situent du côté de PHP, pas de
MySQL. En effet PHP est un langage très lent.
- Un système de cache par fichiers est très efficace. Sur SPIP, cela rend les pages environ 10 fois plus rapides. Bien sûr, cela dépend de la complexité des pages..
- Le cache par fichiers peut parfaitement être appelé par include() au lieu de fopen() ou readfile(). On peut donc y mettre... du PHP. Cela n'est pas idiot, car les quelques morceaux variant en fonction du visiteur (infos de login, etc.) peuvent être générés en PHP dans les fichiers du cache.
Amicalement, Antoine.
Purges des pages moins fréquentes
Sur un gros wiki, comme wikini.net commence à l'être, la purge des pages peut être relativement longue : plusieurs secondes, quand ce n'est pas plus. Actuellement cette purge est réalisée statistiquement une fois sur trois comme l'indique le code suivant dans /wakka.php :
if(!($this->GetMicroTime?()%3)) $this->Maintenance();
Pourquoi ne pas baisser fortement la fréquence des purges ? J'ai testé avec une valeur d'une fois sur 9 et j'obtiens de très bon résultats. Je pense même qu'on pourrait encore baisser raisonnablement cette fréquence : une fois sur 30 voire une fois sur 100.
Note : sans faire exprès, j'ai passé la valeur une fois sur 9 dans le CVS... je l'y laisse en attendant vos commentaires.
--
CharlesNepote
- L'utilisation de GetMicroTime() est totalement inutile: le modulo convertit de toute façon la valeur en entier d'abord. Cela na pas de conséquence sur la probabilité, mais il serait préférable d'utiliser simplement time(), ou même mieux: rand() -- LordFarquaad
- Oui, très bonne remarque. Je ne me souvient pas pourquoi nous avions choisi GetMicroTime?... Sais-tu si rand() est plus rapide que time() ? Autant choisir le plus rapide. -- CharlesNepote
- Je suppose que time() est bien plus rapide car c'est une "simple" lecture de valeur tandis que rand() est généré sur base d'algorythmes beaucoup plus compliqués. L'inconvéniant c'est que l'utilisation multiple de time() (ou de microtime() d'ailleurs) ne produit évidemment pas des valeurs indépendantes... A noter que pour obtenir des valeurs encore plus aléatoires, il est préférable d'utiliser mt_rand(). Pour un appel unique, il n'y a certainement aucune différence perceptible entre les trois... -- LordFarquaad
- J'ai fait des tests avec time() qui donnent de bons résultats. 9 est également un chiffre qui donne de bons résultats pour un gros wiki comme wikini.net mais je me pose la question des wikis personnels peu consultés... le risque c'est que la purge ne fonctionne pas pendant des jours et des jours...
- Pour moi la purge pourrait même se faire à l'édition, ça me paraîtrait plus simple et aussi plus performant (pas besoin de vérifier toutes les pages d'un coup). Comme inconvéniant il vient que des pages modifiées très rarement peuvent "attendre" longtemps avant d'être purgées... Mais vu qu'elles sont rarement modifiées, il ne devrait pas y avoir trop de versions à purger de toute façon... Je propose d'en discuter sur une page comme HandlerEdit? (je pense qu'edit.php n'a pas une page qui lui est consacrée, si ? On pourrait consacrer une page à chaque handler comme on le fait pour les actions...) -- LordFarquaad
- Je crois que les bases grossiraient trop vite. En tout cas c'est prendre le risque. L'idéal absolu, à mon sens, serait de donner la possibilité de plusieurs politiques de purge (mais c'est effectivement un autre sujet dont il faut discuter sur une autre page ; dans un premier temps je pense que nous pouvons nous concentrer sur l'amélioration de la solution existante, ce qui ne serait déjà pas si mal) :
- purger quotidiennement et automatiquement toute la base en fonction de la taille de la base : lorsque la base dépasse une taille fixée par un paramètre de configuration : avantageux quand on veut conserver le maximum et qu'on est chez un hébergeur qui propose des ressources limitées
- purger quotidiennement et automatiquement toute la base en fonction d'un délai de purge
- Oui c'est vrai qu'au fond une purge quotidienne devrait être largement suffisant, le problème c'est pour stocker la date de la dernière purge... Je crois que l'idéal serait de stocker cette valeur dans la base de données, mais pour cela il faudrait attendre une évolution de WikiNi... Je pense que cela a été proposé dans l'InterfaceDAdministrationWikiNi en fait. Sinon une combinaison purge de la page éditée - purge totale pourrait aussi être une très bonne chose: cela pourrait permettre de réduire considérablement la fréquence de purge totale. (la purge pourrait, par exemple, se faire uniquement s'il y a plus de X pages à supprimer) Ceci serait certainement à considérer après avoir apporté les améliorations que je suggère ci-dessus pour la gestion des versions (si on le fait, mais je pense que ce serait au moins aussi efficace que de travailler sur la purge...)
- Sinon je viens de jetter un oeuil pour la première fois à la méthode PurgePages et euh... elle est vraiment attroce: deux boucles imbriquées avec une requête mysql dans chacune; j'avais déjà vu des horreurs dans WikiNi, mais là ça bat des records ! Encore heureux que la boucle intérieure ne sert strictement à rien, sinon ça pourrait en faire des requêtes ! Il faut absolument la réécrire... On pourrait discuter simplement de ça dans ClasseWikiMethodePurgePages?, non ? -- LordFarquaad
- La boucle intérieure ne sert pas à rien, c'est justement elle qui permet d'effacer les pages. Sinon il y a une discussion pour la faire évoluer sur la page (cf. ProtectionContreLeVandalisme paragraphe 1.3). Je suis d'accord sur le fait que les deux requêtes dans les boucles ne sont pas très heureuses mais n'y a-t-il pas une taille limite de requête SQL au dela de laquelle la requête ne peut plus fonctionner ? (il me semble qu'on s'était posé la question dans ActionRecentChanges à propos du paramètre exclude). (Si tu veux voir les requêtes en action, essaye le mode debug="yes" de wikini, ça te donnera une idée.) -- CharlesNepote
- La boucle intérieure ne sert à rien en tant que boucle, la requête, elle sert, bien sûr. Je m'explique: on fait juste avant une requête du type "SELECT DISTINCT champ FROM table WHERE champ = 'quelque chose'", que peut-on obtenir comme résultats ? La partie champ = 'quelque chose' va nous sortir toutes les lignes dont champ vaut 'quelque chose', de façon insensible à la casse. Ensuite le DISTINCT ne va tirer des résultats que les lignes pour lesquelles champ diffère, et la seule différence d'une ligne à l'autre sera la casse. Dans WikiNi, normalement, le nom de la page est toujours sauvé avec la même casse, donc il n'y aura qu'un seul résultat... (boucle for inutile...) Par ailleurs la requête de suppression fera elle aussi une comparaison avec le signe d'égalité, donc toujours insensible à la casse, ce qui veut dire que même si la requête de sélection avait donné plusieurs lignes de résultats, la première requête les supprimera toutes, et les suivantes seront inutiles... (ce qui fait que la boucle for est d'autant plus inutile...)
- Merci pour ProtectionContreLeVandalisme, même si j'y étais déjà car j'y avais aussi songé ;-) Je vais d'ailleurs sur le champ y proposer ma version, en seulement deux requêtes, jamais plus (moins s'il n'y a rien à supprimmer)
- Pour ce qui est de la longueur des requêtes, je me souviens en effet qu'on en ait discuté, mais j'ai l'impression que ce n'était pas là... D'après mon souvenir ça ne posait vraiment pas de problème (une requête pouvant être vraiment longue, je me demande si ce n'était pas de l'ordre de 1mio) Dans le code que je vais proposer ça a vraiment très peu de chance d'en poser en tout cas -- LordFarquaad
- Ok. Je vais voir tes propositions et on pourra ensuite effacer ça. -- CharlesNepote
LordFarquaadASuivreEnPriorite