[SPIP Zone] optimisation du cache?

Bonjour,

Je suis en train de bosser sur un plugin pour booster le cache, et ce qui me pose problème c’est l’arrivée de la balise #SESSION, mais la n’est pas ma question. En fait je regardais un peu le fonctionnement du cache ‹ sessioné ›, et un principe assez étrange m’a sauté aux yeux…

si on jette un oeil à cacher.php, fonction creer_cache():

// Si la page c1234 a un invalideur de session ‹ zz ›, sauver dans
// ‹ tmp/cache/a/c1234-zz.gz ›
// en prenant soin de supprimer un eventuel cache non-sessionne
// si l’ajout de #SESSION dans le squelette est recent
if (isset($page[‹ invalideurs ›])
AND isset($page[‹ invalideurs ›][‹ session ›])) {
supprimer_fichier(_DIR_CACHE . $chemin_cache);
$chemin_cache .= ‹ - ›.$page[‹ invalideurs ›][‹ session ›];
}

Si j’ai bien compris, si on crée une version ‹ sessionée › d’un cache, on supprime automatiquement la version ‹ non-sessionée › si elle existe?

Mais dans le cas ou un auteur voit une page qui contient la balise #SESSION, c’est la version qu’on vient alors de supprimer qui devait lui être servie, c’est bien cela?

Car si une fois sur deux j’ai un visiteur autentifié et un visiteur non-autentifié qui visitent la même page, le visiteur autentifier va passer son temps à couper l’herbe sous le pied du visiteur anonyme… dans le pire cas de figure. Je comprends bien que le but premier est de virer un cache non sessioné quand on vient d’ajouter la balise #SESSION dans un squelette, mais il est pourtant utile à tous les visiteurs non authentifiés, je me trompe?

est-ce que pour un visiteur non authentifié, à partir du moment ou on a la balise #SESSION dans le squelette, alors le fichier cache finira simplement par ‹ - › et par ‹ -afc45b › pour un autheur identifié? Dans ce cas je comprends l’erreur dans mon raisonnement…

Si j’ai mal compris quelque chose merci de m’éclairer et désolé pour la fausse alerte.

Benoit


Nouveau Windows 7 : Trouvez le PC qui vous convient. En savoir plus.

Le 30 oct. 2009 à 17:14, Benoit Aubert a écrit :

Bonjour,

Je suis en train de bosser sur un plugin pour booster le cache,

Qu’appeles-tu ‹ booster › le cache ?
Le plugin FastCache ne fait pas ton affaire ?
Tu penses à une logique différente ?
On est toujours à la recherche d’une amélioration qui pourrait bénéficier à tous, donc ça nous intéresse.

et ce qui me pose problème c’est l’arrivée de la balise #SESSION, mais la n’est pas ma question. En fait je regardais un peu le fonctionnement du cache ‹ sessioné ›, et un principe assez étrange m’a sauté aux yeux…

si on jette un oeil à cacher.php, fonction creer_cache():

// Si la page c1234 a un invalideur de session ‹ zz ›, sauver dans
// ‹ tmp/cache/a/c1234-zz.gz ›
// en prenant soin de supprimer un eventuel cache non-sessionne
// si l’ajout de #SESSION dans le squelette est recent
if (isset($page[‹ invalideurs ›])
AND isset($page[‹ invalideurs ›][‹ session ›])) {
supprimer_fichier(_DIR_CACHE . $chemin_cache);
$chemin_cache .= ‹ - ›.$page[‹ invalideurs ›][‹ session ›];
}

Si j’ai bien compris, si on crée une version ‹ sessionée › d’un cache, on supprime automatiquement la version ‹ non-sessionée › si elle existe?

Mais dans le cas ou un auteur voit une page qui contient la balise #SESSION, c’est la version qu’on vient alors de supprimer qui devait lui être servie, c’est bien cela?

Non. A partir du moment ou la balise #SESSION est présente dans un squelette, toutes les versions sont ‹ sessionnées ›. Seule la valeur de l’identifiant de session change.
En l’occurrence, pour un visiteur, l’identifiant de session correspondra à une session vide.

Et sinon, question subsidiaire, si tu travailles sur ce sujet, c’est que tu dois avoir des problèmes de performances, non ?
Peut-être tu peux nous en dire un peu plus ?

Cédric

Le 30 oct. 2009 à 19:54, Benoit Aubert a écrit :

En fait mon plugin est très proche du système de cache SPIP actuel. Il s’agit de ne plus construire les caches devant le visiteur dans la mesure du possible, c’est tout. Quand un cache existe, mais est trop vieux et doit être rafraichit, au lieu de le recréer au moment ou le visiteur affiche sa page (ce qui prend un peu de temps, même infime), on insère dans une table tous les éléments du contexte qui sont utiles à la construction de ce cache, et on affiche encore le cache expiré.

Ensuite j’ai un cron qui va lui lire de manière régulière les lignes de ma table et créer en dehors de la navigation des visiteurs mes blocs de cache et les enregistrer.

OK, peut-être que le plugin job_queue pourrait t’être utile : il permet d’insérer en file d’attente des taches a faire
http://zone.spip.org/trac/spip-zone/browser/plugins/job_queue

Du coup ça pourrait faire un diff assez simple :
(écriture de principe, à tester et valider)

Index: ecrire/public/assembler.php

— ecrire/public/assembler.php (revision 14613)
+++ ecrire/public/assembler.php (working copy)
@@ -114,13 +114,20 @@
if (!strlen($fond))
$fond = ‹ sommaire ›;

  • // preparer le contexte
  • $parametrer = charger_fonction(‹ parametrer ›, ‹ public ›);
  • $page = $parametrer($fond, $GLOBALS[‹ contexte ›], $chemin_cache, $connect);
  • if ($use_cache==2 AND defined(‹ _DIR_PLUGIN_QUEUE ›)) {
  • // demande d’un _CACHE_DELAYED
  • // on ajoute le travail a la liste des jobs
  • job_queue_add(‹ parametrer ›,« Calcul du cache $fond / $url »,array($fond, $GLOBALS[‹ contexte ›], $chemin_cache, $connect),« public/ »,TRUE);
  • }
  • else {
  • // preparer le contexte
  • $parametrer = charger_fonction(‹ parametrer ›, ‹ public ›);
  • $page = $parametrer($fond, $GLOBALS[‹ contexte ›], $chemin_cache, $connect);
  • // Stocker le cache sur le disque
  • if ($chemin_cache)
  • $cacher(NULL, $use_cache, $chemin_cache, $page, $lastmodified);
  • // Stocker le cache sur le disque
  • if ($chemin_cache)
  • $cacher(NULL, $use_cache, $chemin_cache, $page, $lastmodified);
  • }
    }

if ($chemin_cache) $page[‹ cache ›] = $chemin_cache;
@@ -216,14 +223,21 @@
if (!$use_cache) {
$lastmodified = max($lastmodified, $lastinclude);
} else {

  • $parametrer = charger_fonction(‹ parametrer ›, ‹ public ›);
  • $page = $parametrer($fond, $contexte, $chemin_cache, $connect);
  • $lastmodified = time();
  • // et on l’enregistre sur le disque
  • if ($chemin_cache
  • AND $page[‹ entetes ›][‹ X-Spip-Cache ›] > 0)
  • $cacher($contexte, $use_cache, $chemin_cache, $page,
  • $lastmodified);
  • if ($use_cache==2 AND defined(‹ _DIR_PLUGIN_QUEUE ›)) {
  • // demande d’un _CACHE_DELAYED
  • // on ajoute le travail a la liste des jobs
  • job_queue_add(‹ parametrer ›,« Calcul du cache $fond / inclure_page »,array($fond, $contexte, $chemin_cache, $connect),« public/ »,TRUE);
  • }
  • else {
  • $parametrer = charger_fonction(‹ parametrer ›, ‹ public ›);
  • $page = $parametrer($fond, $contexte, $chemin_cache, $connect);
  • $lastmodified = time();
  • // et on l’enregistre sur le disque
  • if ($chemin_cache
  • AND $page[‹ entetes ›][‹ X-Spip-Cache ›] > 0)
  • $cacher($contexte, $use_cache, $chemin_cache, $page,
  • $lastmodified);
  • }
    }

return $page;
Index: ecrire/public/cacher.php

— ecrire/public/cacher.php (revision 14613)
+++ ecrire/public/cacher.php (working copy)
@@ -126,8 +126,12 @@
$duree = intval($page[‹ entetes ›][‹ X-Spip-Cache ›]);
if ($duree == 0) #CACHE{0}
return -1;

  • else if ($date + $duree < time())
  • return 1;
  • else if ($date + $duree < time()){
  • if (defined(‹ _CACHE_DELAYED ›) AND _CACHE_DELAYED) // si on demande un calcul retarde du cache
  • return 2;
  • else
  • return 1;
  • }
    else
    return 0;
    }

Ensuite, charge au webmestre qui en a besoin d’utiliser _CACHE_DELAYED pour activer le calcul différé du cache :

  • tout le temps
  • quand son load est trop fort
  • quand ça lui chante …
  • quand c’est un visiteur non contributeur …

J’ai déjà évoqué ce système à un programmeur de SPIP, mais l’intérêt n’a pas semblé évident,

Je crois bien que c’était avec moi :stuck_out_tongue:

donc je développe ce plugin de mon côté, et sur des sites à gros traffic, on a noté une sérieuse baisse de la charge du serveur pendant les pics de traffic, moment ou on doit construire plus de caches. Ce système avait pour but premier un plus grand confort pour le visiteur avec plus de rapidité, mais il s’est avéré qu’avec un cron job lancé à une cadence régulière, ca étalait le load du serveur de manière très significative.

Est-ce que tu as mis en place quelque chose contre les bots ?
L’expérience montre qu’une très grosse part du calcul des caches est provoquée par les bots des moteurs de recherche, et ceux-ci n’ont pas vraiment besoin d’être servis quand ils le demandent : on peut leur demander de revenir plus tard.
cf http://zone.spip.org/trac/spip-zone/browser/core/securite/ecran_securite.php#L159

L’intérêt par rapport à fastcache et expresso, c’est qu’on n’enregistre pas de pages statiques, mais on utilise simplement le cache de spip en construisant le plus de fichiers possibles en tache de fond plutot qu’au moment de la présentation.

On garde un dynamisme proche du système actuel, mais la durée de vie des caches est légèrmeent prolongée, et dépend du nombre de lignes dans la table (file d’atente de rafraichissement) et la fréquence du cron. En général on arrive à construire un fichier cache quelques minutes après que son expiration n’ait été détéctée par une visite de la page qui le contient. J’ai ce plugin depuis la 1.8, mais il n’a jamais tourné parfaitement et je filtrais quelques exceptions de manière très aproximative, je change complètement d’endroit pour l’interception des caches en ce moment, et je suis en train d’essayer de rendre ce plugin fiable pour la 2.0.

Après tout, on met dans la plupart de nos cache des temps de vie de plusieurs heures ou plusieurs jours, ca veut bien dire qu’on n’est pas à 5 minutes près.

Oui, c’est souvent vrai.
Sauf pour les contributeurs du site qui ne comprennent pas lorsqu’ils voient une page pas a jour :stuck_out_tongue:
Dans le cas d’un site éditorial simple, ce serait pour le coup assez facile de ne pas différer le calcul pour que les contributeurs voient les pages à jour.
Mais lorsque le site a un certain caractère collaboratif, il est difficile de retarder les mises à jour.

Si ce système semble inutile (il l’est pour des ‹ petits › sites), sur un site à grand contenu et avec un traffic élevé le changement est assez significatif.

Merci pour la réponse à ma question, j’avais un doute ca m’arrange ce système.

Pour répondre à ta question, oui on souhaite améliorer nos performances, comme je te dis on bosse sur des sites avec un traffic relativement élevé (www.topspeed.com principalement), et on voudrait pouvoir mutualiser tous nos sites sur un même serveur (au moindre cout), sans avoir de montagnes russes sur notre load, ce qui prend des ampleurs exponentielles et catastrophiques à court terme quand un process commence à bloquer ou partir en vrille.

Si un patch dans le sens de ce que je te propose plus haut te parait utile et montre un intérêt, on peut sans doute l’intégrer dans la prochaine version, ce qui permettrait ensuite aux webmestres avancés de jouer avec sans perturber le fonctionnement de l’existant pour les autres.

Cédric

Le patch précédent était incorrect.
Voici une version testée qui semble correspondre à ce que tu vises.
Par curiosité je viens de le mettre en service sur SPIP-Contrib.

Index: ecrire/public/assembler.php

--- ecrire/public/assembler.php (revision 14613)
+++ ecrire/public/assembler.php (working copy)
@@ -114,13 +114,12 @@
                         if (!strlen($fond))
                                 $fond = 'sommaire';

- // preparer le contexte
- $parametrer = charger_fonction('parametrer', 'public');
- $page = $parametrer($fond, $GLOBALS['contexte'], $chemin_cache, $connect);
-
- // Stocker le cache sur le disque
- if ($chemin_cache)
- $cacher(NULL, $use_cache, $chemin_cache, $page, $lastmodified);
+ if ($use_cache==2 AND defined('_DIR_PLUGIN_QUEUE'))
+ // demande d'un _CACHE_DELAYED
+ // on ajoute le travail a la liste des jobs
+ job_queue_add('produire_page',"Calcul du cache $fond [$url]",array($fond, $GLOBALS['contexte'], $chemin_cache, NULL, $use_cache, $connect),"public/assembler",TRUE);
+ else
+ $page = produire_page($fond,$GLOBALS['contexte'],$chemin_cache,NULL,$use_cache,$connect);
                 }

                 if ($chemin_cache) $page['cache'] = $chemin_cache;
@@ -216,19 +215,34 @@
         if (!$use_cache) {
                 $lastmodified = max($lastmodified, $lastinclude);
         } else {
- $parametrer = charger_fonction('parametrer', 'public');
- $page = $parametrer($fond, $contexte, $chemin_cache, $connect);
- $lastmodified = time();
- // et on l'enregistre sur le disque
- if ($chemin_cache
- AND $page['entetes']['X-Spip-Cache'] > 0)
- $cacher($contexte, $use_cache, $chemin_cache, $page,
- $lastmodified);
+ if ($use_cache==2 AND defined('_DIR_PLUGIN_QUEUE'))
+ // demande d'un _CACHE_DELAYED
+ // on ajoute le travail a la liste des jobs
+ job_queue_add('produire_page',"Calcul du cache $fond [inclure_page]",array($fond, $contexte, $chemin_cache, $contexte, $use_cache, $connect),"public/assembler",TRUE);
+ else
+ $page = produire_page($fond, $contexte, $chemin_cache, $contexte, $use_cache, $connect);
         }

         return $page;
  }

+
+function produire_page($fond, $contexte, $chemin_cache, $contexte_cache, $use_cache, $connect){
+ $parametrer = charger_fonction('parametrer', 'public');
+ $page = $parametrer($fond, $contexte, $chemin_cache, $connect);
+ // et on l'enregistre sur le disque
+ if ($chemin_cache
+ AND $page['entetes']['X-Spip-Cache'] > 0){
+ $cacher = charger_fonction('cacher', 'public');
+ $lastmodified = time();
+ if ($use_cache>1) $use_cache=1;
+ $cacher($contexte_cache, $use_cache, $chemin_cache, $page,
+ $lastmodified);
+ }
+ return $page;
+}
+
  # Attention, un appel explicite a cette fonction suppose certains include
  # $echo = faut-il faire echo ou return

Index: ecrire/public/cacher.php

--- ecrire/public/cacher.php (revision 14613)
+++ ecrire/public/cacher.php (working copy)
@@ -126,8 +126,12 @@
         $duree = intval($page['entetes']['X-Spip-Cache']);
         if ($duree == 0) #CACHE{0}
                 return -1;
- else if ($date + $duree < time())
- return 1;
+ else if ($date + $duree < time()){
+ if (defined('_CACHE_DELAYED') AND _CACHE_DELAYED) // si on demande un calcul retarde du cache
+ return 2;
+ else
+ return 1;
+ }
         else
                 return 0;
  }

Je continue a améliorer la proposition :

Du côté du core, j'ai introduit dans la branche dev le patch suivant (applicable aussi sur la branche stable)
http://trac.rezo.net/trac/spip/changeset/14703
qui permet une personnalisation de la fonction public_produire_dist

Un exemple (imparfait) est alors d'ajouter dans config/mes_options (ou dans le fichier options d'un plugin) :

function public_produire_page($fond, $contexte, $use_cache, $chemin_cache, $contexte_cache, $page, &$lastinclude, $connect=''){
  // calcul differe du cache ?
  if (is_array($page)
    AND count($page)
    AND defined('_DIR_PLUGIN_QUEUE')
# AND !$GLOBALS['visiteur_session']['id_auteur']
    ) {
    // on differe la maj du cache et on affiche le contenu du cache ce coup ci encore
    $where = is_null($contexte_cache)?"principal":"inclure_page";
    job_queue_add('public_produire_page',$c="Calcul du cache $fond [$where]",array($fond, $contexte, $use_cache, $chemin_cache, $contexte_cache, NULL, $lastinclude, $connect),"",TRUE);
    gunzip_page(&$page); // decomprimer la page si besoin
    spip_log($c,'cachedelai');
    return $page;
  }

  include_spip('public/assembler');
  return public_produire_page_dist($fond, $contexte, $use_cache, $chemin_cache, $contexte_cache, $page, $lastinclude, $connect);
}

Je dis que l'exemple est imparfait car avec cette fonction, si le cache est calculé dans la queue par un cron exécuté depuis le privé, les urls sont référencées par rapport à ecrire/, donc commencent par un ../.
De même, dans ce cas l'en-tete est compressé car c'est le réglage par défaut de ecrire/

C'est un cas d'école intéressant qui n'était pas prévu pour job_queue, et il faut réflechir pour savoir si la queue doit prendre en charge ce type de besoin ou pas.
Si oui il faudrait alors pouvoir préciser le contexte d'execution de la queue (public/prive), et ensuite être capable de se placer dans le même contexte.

Cédric

Le 30 oct. 2009 à 21:41, cedric.morin@yterium.com a écrit :

Le patch précédent était incorrect.
Voici une version testée qui semble correspondre à ce que tu vises.
Par curiosité je viens de le mettre en service sur SPIP-Contrib.

Tiens, toi aussi tu vérifies tes patchs après les faire ? ... :slight_smile:
Le 30 oct. 2009 à 21:41, cedric.morin@yterium.com a écrit :

Le patch précédent était incorrect.
Voici une version testée qui semble correspondre à ce que tu vises.
Par curiosité je viens de le mettre en service sur SPIP-Contrib.

Index: ecrire/public/assembler.php

--- ecrire/public/assembler.php (revision 14613)
+++ ecrire/public/assembler.php (working copy)
@@ -114,13 +114,12 @@
                       if (!strlen($fond))
                               $fond = 'sommaire';

- // preparer le contexte
- $parametrer = charger_fonction('parametrer', 'public');
- $page = $parametrer($fond, $GLOBALS['contexte'], $chemin_cache, $connect);
-
- // Stocker le cache sur le disque
- if ($chemin_cache)
- $cacher(NULL, $use_cache, $chemin_cache, $page, $lastmodified);
+ if ($use_cache==2 AND defined('_DIR_PLUGIN_QUEUE'))
+ // demande d'un _CACHE_DELAYED
+ // on ajoute le travail a la liste des jobs
+ job_queue_add('produire_page',"Calcul du cache $fond [$url]",array($fond, $GLOBALS['contexte'], $chemin_cache, NULL, $use_cache, $connect),"public/assembler",TRUE);
+ else
+ $page = produire_page($fond,$GLOBALS['contexte'],$chemin_cache,NULL,$use_cache,$connect);
               }

               if ($chemin_cache) $page['cache'] = $chemin_cache;
@@ -216,19 +215,34 @@
       if (!$use_cache) {
               $lastmodified = max($lastmodified, $lastinclude);
       } else {
- $parametrer = charger_fonction('parametrer', 'public');
- $page = $parametrer($fond, $contexte, $chemin_cache, $connect);
- $lastmodified = time();
- // et on l'enregistre sur le disque
- if ($chemin_cache
- AND $page['entetes']['X-Spip-Cache'] > 0)
- $cacher($contexte, $use_cache, $chemin_cache, $page,
- $lastmodified);
+ if ($use_cache==2 AND defined('_DIR_PLUGIN_QUEUE'))
+ // demande d'un _CACHE_DELAYED
+ // on ajoute le travail a la liste des jobs
+ job_queue_add('produire_page',"Calcul du cache $fond [inclure_page]",array($fond, $contexte, $chemin_cache, $contexte, $use_cache, $connect),"public/assembler",TRUE);
+ else
+ $page = produire_page($fond, $contexte, $chemin_cache, $contexte, $use_cache, $connect);
       }

       return $page;
}

+
+function produire_page($fond, $contexte, $chemin_cache, $contexte_cache, $use_cache, $connect){
+ $parametrer = charger_fonction('parametrer', 'public');
+ $page = $parametrer($fond, $contexte, $chemin_cache, $connect);
+ // et on l'enregistre sur le disque
+ if ($chemin_cache
+ AND $page['entetes']['X-Spip-Cache'] > 0){
+ $cacher = charger_fonction('cacher', 'public');
+ $lastmodified = time();
+ if ($use_cache>1) $use_cache=1;
+ $cacher($contexte_cache, $use_cache, $chemin_cache, $page,
+ $lastmodified);
+ }
+ return $page;
+}
+
# Attention, un appel explicite a cette fonction suppose certains include
# $echo = faut-il faire echo ou return

Index: ecrire/public/cacher.php

--- ecrire/public/cacher.php (revision 14613)
+++ ecrire/public/cacher.php (working copy)
@@ -126,8 +126,12 @@
       $duree = intval($page['entetes']['X-Spip-Cache']);
       if ($duree == 0) #CACHE{0}
               return -1;
- else if ($date + $duree < time())
- return 1;
+ else if ($date + $duree < time()){
+ if (defined('_CACHE_DELAYED') AND _CACHE_DELAYED) // si on demande un calcul retarde du cache
+ return 2;
+ else
+ return 1;
+ }
       else
               return 0;
}

_______________________________________________
spip-zone@rezo.net - http://listes.rezo.net/mailman/listinfo/spip-zone

----

PRIGENT Yohann
Répondre à ce mail à l'adresse prigent.yohann@gmail.com, Merci !

ah ben oui, mais je demande pas à ce qu'ils soient intégrés au core :stuck_out_tongue:
et puis j'avais prévenu que mon premier patch était "théorique"

Cédric

Le 31 oct. 2009 à 21:29, Yohann Prigent a écrit :

Tiens, toi aussi tu vérifies tes patchs après les faire ? ... :slight_smile:
Le 30 oct. 2009 à 21:41, cedric.morin@yterium.com a écrit :

Le patch précédent était incorrect.
Voici une version testée qui semble correspondre à ce que tu vises.
Par curiosité je viens de le mettre en service sur SPIP-Contrib.

Index: ecrire/public/assembler.php

--- ecrire/public/assembler.php (revision 14613)
+++ ecrire/public/assembler.php (working copy)
@@ -114,13 +114,12 @@
                      if (!strlen($fond))
                              $fond = 'sommaire';

- // preparer le contexte
- $parametrer = charger_fonction('parametrer', 'public');
- $page = $parametrer($fond, $GLOBALS['contexte'], $chemin_cache, $connect);
-
- // Stocker le cache sur le disque
- if ($chemin_cache)
- $cacher(NULL, $use_cache, $chemin_cache, $page, $lastmodified);
+ if ($use_cache==2 AND defined('_DIR_PLUGIN_QUEUE'))
+ // demande d'un _CACHE_DELAYED
+ // on ajoute le travail a la liste des jobs
+ job_queue_add('produire_page',"Calcul du cache $fond [$url]",array($fond, $GLOBALS['contexte'], $chemin_cache, NULL, $use_cache, $connect),"public/assembler",TRUE);
+ else
+ $page = produire_page($fond,$GLOBALS['contexte'],$chemin_cache,NULL,$use_cache,$connect);
              }

              if ($chemin_cache) $page['cache'] = $chemin_cache;
@@ -216,19 +215,34 @@
      if (!$use_cache) {
              $lastmodified = max($lastmodified, $lastinclude);
      } else {
- $parametrer = charger_fonction('parametrer', 'public');
- $page = $parametrer($fond, $contexte, $chemin_cache, $connect);
- $lastmodified = time();
- // et on l'enregistre sur le disque
- if ($chemin_cache
- AND $page['entetes']['X-Spip-Cache'] > 0)
- $cacher($contexte, $use_cache, $chemin_cache, $page,
- $lastmodified);
+ if ($use_cache==2 AND defined('_DIR_PLUGIN_QUEUE'))
+ // demande d'un _CACHE_DELAYED
+ // on ajoute le travail a la liste des jobs
+ job_queue_add('produire_page',"Calcul du cache $fond [inclure_page]",array($fond, $contexte, $chemin_cache, $contexte, $use_cache, $connect),"public/assembler",TRUE);
+ else
+ $page = produire_page($fond, $contexte, $chemin_cache, $contexte, $use_cache, $connect);
      }

      return $page;
}

+
+function produire_page($fond, $contexte, $chemin_cache, $contexte_cache, $use_cache, $connect){
+ $parametrer = charger_fonction('parametrer', 'public');
+ $page = $parametrer($fond, $contexte, $chemin_cache, $connect);
+ // et on l'enregistre sur le disque
+ if ($chemin_cache
+ AND $page['entetes']['X-Spip-Cache'] > 0){
+ $cacher = charger_fonction('cacher', 'public');
+ $lastmodified = time();
+ if ($use_cache>1) $use_cache=1;
+ $cacher($contexte_cache, $use_cache, $chemin_cache, $page,
+ $lastmodified);
+ }
+ return $page;
+}
+
# Attention, un appel explicite a cette fonction suppose certains include
# $echo = faut-il faire echo ou return

Index: ecrire/public/cacher.php

--- ecrire/public/cacher.php (revision 14613)
+++ ecrire/public/cacher.php (working copy)
@@ -126,8 +126,12 @@
      $duree = intval($page['entetes']['X-Spip-Cache']);
      if ($duree == 0) #CACHE{0}
              return -1;
- else if ($date + $duree < time())
- return 1;
+ else if ($date + $duree < time()){
+ if (defined('_CACHE_DELAYED') AND _CACHE_DELAYED) // si on demande un calcul retarde du cache
+ return 2;
+ else
+ return 1;
+ }
      else
              return 0;
}

_______________________________________________
spip-zone@rezo.net - http://listes.rezo.net/mailman/listinfo/spip-zone

----

PRIGENT Yohann
Répondre à ce mail à l'adresse prigent.yohann@gmail.com, Merci !

Le 31 oct. 2009 à 21:36, cedric.morin@yterium.com a écrit :

ah ben oui, mais je demande pas à ce qu'ils soient intégrés au core :stuck_out_tongue:

normal, c'est toi le dev core !
il en est à quel stade de validation mon patch, il a passé la validation :stuck_out_tongue: ?

----

PRIGENT Yohann
Répondre à ce mail à l'adresse prigent.yohann@gmail.com, Merci !

Et finalement, cela donne

Qui tourne en prod sur SPIP-Contrib et sur http://www.cuisine-libre.fr
Les petits bug du départ ont été résolus.

En terme de temps de réponse perceptible par le visiteur, je note un gain significatif qui se traduit par une homogénéité du temps de réponse rapide, correspondant au service rapide d'une page tout en cache, et se ressent comme une rapidité générale du site et un confort de navigation.
Cela vaut surtout si le site a suffisamment de trafic pour que l'ensemble du cache soit toujours assez frais (et qui suppose que l'espace alloué au cache soit assez gros pour pouvoir garder une copie à peu près complète).

En terme de charge serveur, je n'ai pas assez de recul pour voir si il y a un gain. On peut supposer que l'on gagne au moins les calculs concourants d'un même cache, qui n'ont plus lieu. Mais on perd aussi une insertion SQL+un delete pour chaque calcul de cache en background.

Cédric

Le 31 oct. 2009 à 12:03, cedric.morin@yterium.com a écrit :

Je continue a améliorer la proposition :

Du côté du core, j'ai introduit dans la branche dev le patch suivant (applicable aussi sur la branche stable)
http://trac.rezo.net/trac/spip/changeset/14703
qui permet une personnalisation de la fonction public_produire_dist

Un exemple (imparfait) est alors d'ajouter dans config/mes_options (ou dans le fichier options d'un plugin) :

function public_produire_page($fond, $contexte, $use_cache, $chemin_cache, $contexte_cache, $page, &$lastinclude, $connect=''){
  // calcul differe du cache ?
  if (is_array($page)
    AND count($page)
    AND defined('_DIR_PLUGIN_QUEUE')
# AND !$GLOBALS['visiteur_session']['id_auteur']
    ) {
    // on differe la maj du cache et on affiche le contenu du cache ce coup ci encore
    $where = is_null($contexte_cache)?"principal":"inclure_page";
    job_queue_add('public_produire_page',$c="Calcul du cache $fond [$where]",array($fond, $contexte, $use_cache, $chemin_cache, $contexte_cache, NULL, $lastinclude, $connect),"",TRUE);
    gunzip_page(&$page); // decomprimer la page si besoin
    spip_log($c,'cachedelai');
    return $page;
  }

  include_spip('public/assembler');
  return public_produire_page_dist($fond, $contexte, $use_cache, $chemin_cache, $contexte_cache, $page, $lastinclude, $connect);
}

Je dis que l'exemple est imparfait car avec cette fonction, si le cache est calculé dans la queue par un cron exécuté depuis le privé, les urls sont référencées par rapport à ecrire/, donc commencent par un ../.
De même, dans ce cas l'en-tete est compressé car c'est le réglage par défaut de ecrire/

C'est un cas d'école intéressant qui n'était pas prévu pour job_queue, et il faut réflechir pour savoir si la queue doit prendre en charge ce type de besoin ou pas.
Si oui il faudrait alors pouvoir préciser le contexte d'execution de la queue (public/prive), et ensuite être capable de se placer dans le même contexte.

Cédric

Le 30 oct. 2009 à 21:41, cedric.morin@yterium.com a écrit :

Le patch précédent était incorrect.
Voici une version testée qui semble correspondre à ce que tu vises.
Par curiosité je viens de le mettre en service sur SPIP-Contrib.

_______________________________________________
spip-zone@rezo.net - http://listes.rezo.net/mailman/listinfo/spip-zone

Bonjour,

Retour d’expérience,
après avoir installé les 2 plugins cache_cool et job_queue et le patch assembler.php et cacher.php (r14703) sur une spip2.0.10, j’ai obtenu
Fatal error: Call to undefined function: trouve_modele() in /var/alternc/html/g/genrespluriels/spip/ecrire/public/assembler.php on line 500

Je lis sur le
http://www.spip-contrib.net/Cache-Cool,3251:

Pour que le plugin soit efficace, il faut que votre site reçoive un trafic suffisamment important pour que les caches en attente soient calculés rapidement.

Est-ce que l’on pourrait préciser la fréquentation du site, style spip-contrib ?

Pour un site moins important
Exemple: 200 visites par jour et 6.000 visites par mois, est-ce suffisamment important ?

bàv,

damazone

Le 1 nov. 2009 à 14:12, damazone a écrit :

Bonjour,

Retour d’expérience,
après avoir installé les 2 plugins cache_cool et job_queue et le patch assembler.php et cacher.php (r14703) sur une spip2.0.10, j’ai obtenu
Fatal error: Call to undefined function: trouve_modele() in**/var/alternc/html/g/genrespluriels/spip/ecrire/public/assembler.php** on line 500

Il ne faut pas copier les 2 fichier de la version dev sur la version 2.0.10, mais juste appliquer les memes modifications sur le fichier d’origine de la 2.0.10

Je lis sur le
http://www.spip-contrib.net/Cache-Cool,3251:

Pour que le plugin soit efficace, il faut que votre site reçoive un trafic suffisamment important pour que les caches en attente soient calculés rapidement.

Est-ce que l’on pourrait préciser la fréquentation du site, style spip-contrib ?

Pour un site moins important
Exemple: 200 visites par jour et 6.000 visites par mois, est-ce suffisamment important ?

A voir. Mais cela me parait faible, avec un nombre de visite comme celui-la le cache va être assez vieux en moyenne.
A titre indicatif, divise le nombre moyen d’urls ayant une visite chaque jour par le nombre de visiteur pour avoir une idée de la période de temps entre 2 visites sur la même page.
Cela te donnera l’age moyen du cache servi froid pour un visiteur.
C’est à toi de voir si c’est assez récent compte tenu des mises à jour éditoriales.

Pour info, SPIP Contrib a plus de 6000 visites/jour, mais a peut-être beaucoup plus de pages.

Cédric

Oups, oublié de mettre la zone

---------- Message transféré ----------
De : Cédric Morin <cedric.morin@yterium.com>
Date : 2 novembre 2009 13:05
Objet : Re: [SPIP Zone] optimisation du cache?
À : Benoit Aubert <benoit.aubert@hotmail.fr>

Le 2 novembre 2009 12:48, Benoit Aubert <benoit.aubert@hotmail.fr> a écrit :

Merci pour cette modif. Je suis content de voir que je me positionnais au bon endroit pour l’appliquer, même si ca t’a pris bien moins de temps pour y parvenir.

Sur topspeed.com on a plusieurs milliers de visites par jour, plusieurs dixaines de milliers de fichiers dans chaque sous-dossier du cache. On sera forcément soulagés par cette modif. En ce qui concerne le confort de visite, c’est ce qui nous a frappé en premier sur mes versions précédentes de cette modif, la où on attendait toujours le chargement d’un ou deux blocs sur la page, dès lors on rechargeait la page de manière instantanée si bien qu’on avait l’impression que l’entête ne se rechargeait même pas.

Oui du point de vue du visiteur je suis d’accord avec toi, c’est flagrant.
Du point de vue du serveur je n’ai pas encore de recul pour voir si il y a un effet clair.

On passera tout le traffic de topspeed.com sur la version 2.0.1 de SPIP d’ici un ou deux mois, sois assuré que tu auras un suivi de ce patch avec nous au cas ou des problèmes interviennent.

petites réflexions:

-je ne saisis pas encore en quoi ca pose un soucis pour des contributeurs d’être à la merci de ce patch. Quand on invalide un cache on le supprime directement du disque, ainsi on est obligé de le recalculer à la visite suivante, non?

Non, dans SPIP 2.0, l’invalidation de cache ne supprime plus de fichier.
Pour des raisons de perf globale, il a été choisie de ne plus faire une invalidation fichier à fichier car le gain supposé sur la finesse de l’invalidation était perdu sur l’énergie passée à savoir quel fichier invalider. Du coup quand une action demande une invalidation suite à une modif édirotiale, un flag est levé dans les meta (en fait c’est une date de derniere modif), et cela entraine le calcul de tous les caches antérieurs.
Dans les fait, les fichiers ne sont pas supprimés et sont toujours dispo pour être servis aux visiteurs par le plugin, qui lance ensuite le rafraichissement en tache de fond.

Le seul cas de suppression d’un fichier de cache correspond à la purge du cache pour cause de volume global trop important.

-a l’heure actuelle, les membres connectés peuvent-ils lancer la tâche de fond qui construit les caches de la file? Au niveau des caches sessionés, je me disais que le comportement de ce patch est un peu maladroit, car si par exemple un visiteur non connecté insère une ligne dans la file (concernée par la balise #SESSION), et qu’un membre connecté lance la tâche de fond, alors il va construire une série de fichier caches (pour les sessionés) avec sa propre extension, ce qui non seuelemtn construira plein de fihciers cache sans grand intérêt (pages qu’il ne visitera jamais), mais en plus anulera l’insertion dans la file et peut prolonger ainsi, plusieurs fois à la suite dans le pire des cas, le rafraichissement d’un cache).

Suis-je dans le vrai?

Oui tu as raison, c’est un bug du plugin car je n’avais pas pensé au scenario que to donnes.
Mais c’est même pire, car le calcul en tache de fond par le visiteur connecté sera stocké dans le cache pour le visiteur non connecté.
Le correctif est simple, il faut vider la session avant le calcul des caches en background (et restaurer le contexte de session après au cas où elle servirait pour une autre tache cron).

Comment ca se passe en ce moment pour invalider un cache, depuis que la table spip_cache a disparu?

Comme dit plus haut, juste un flag de levé, sans suppression de fichier.

Cédric

Pour notre site (topspeed.com), avec le trafic et le nombre de caches qu’on a ça revient à plusieurs centaines d’insertions dans job_queue à la minute. Est-ce que le plugin job_queue pourra gérer une liste qui croit à ce rythme sans soucis? A l’heure ou je parle je suis en train de regarder et la table de mon plugin grossit de 10 à 30 lignes par seconde. Je viens de regarder une période complète de remplissage, on est monté à 3000 lignes environ, pour subittement redescendre à 0 (lancement du cron job). C’est effréné car on est en plein pic de traffic la, ce qui au passage ne se repère pas du tout sur la charge CPU du serveur. Notez qu’on a un grand cache car on souhaite servir le plus de pages possible à partir du cache (environ 55000 fichiers par dossier donc environ 900 000 fichiers cache au total).

Dans mon plugin je régle un cron qui tourne toutes les 90 secondes (en théorie, mais on a beaucoup de taches dans cron.php donc c’est un peu plus), et traite à chaque passage au maximum 300 lignes de la table avec un DISTINCT (rafraichissant donc jusqu’à 300 blocs différents de cache).

Ca amène à mon autre question: je m’assure aussi dans mon plugin qu’une fois une ligne traitée, tous ses doublons soient alors supprimés de la table, car entre le moment ou un cache expire et le moment ou on le rafraichit en tâche de fond, d’autres visiteurs insérent exactement la même ligne. Mon petit monitoring ci-dessus le montre bien. Les facteurs sont par exemple des blocs très visités, surtout si on souhaite les rafraichir relativement régulièrement (plusieurs fois par jour), et surtout des pages composées de beaucoup de blocs (je sais c’est pas recommandé). Et ca s’agrave si on a un mauvais concours de circonstances (genre une série de tâches qui monopolisent le cron quelques minutes).

Bref faire deux ou trois fois le même calcul de cache en quelques minutes c’est une perte de temps et de ressources, et dans mon système c’est tout simplement vital pour trouver un équilibre entre fréquence de lancement du cron et nombre de lignes traitées par lancement, le tout pour éviter que la table ne se remplisse plus rapidement qu’elle ne se vide. On a essayé de faire la vérification en amont (insérer dans la table uniquement si la ligne n’existe pas déjà), mais ce process se déroulait alors au moment ou on présente la page au visiteur, ce qui ne va pas dans l’esprit du plugin. Ainsi on a décidé de faire le distinct en aval (dans le cron job), et effacer tous les doublons à chaque construction. Le résultat est un rythme d’insertion très soutenu, et de grandes variations dans la taille de la table, mais au final on redescent toujours à 0 ou presque à la fin d’un cycle, ce qui assure un rafraichissement des caches conforme à la date de la visite alors qu’il est expiré + 2 minutes.

J’espère avoir bien expliqué mon idée et que le plugin cache cool s’y adaptera. Sinon je pense que je devrai le bricoler un peu pour qu’il supporte notre site.

Benoit.

Subject: Re: [SPIP Zone] optimisation du cache?
From: cedric.morin@yterium.com
Date: Sun, 1 Nov 2009 11:32:06 +0100
CC: spip-zone@rezo.net
To: benoit.aubert@hotmail.fr

Et finalement, cela donne
Cache Cool - SPIP-Contrib

Qui tourne en prod sur SPIP-Contrib et sur http://www.cuisine-libre.fr
Les petits bug du départ ont été résolus.

En terme de temps de réponse perceptible par le visiteur, je note un
gain significatif qui se traduit par une homogénéité du temps de
réponse rapide, correspondant au service rapide d’une page tout en
cache, et se ressent comme une rapidité générale du site et un confort
de navigation.
Cela vaut surtout si le site a suffisamment de trafic pour que
l’ensemble du cache soit toujours assez frais (et qui suppose que
l’espace alloué au cache soit assez gros pour pouvoir garder une copie
à peu près complète).

En terme de charge serveur, je n’ai pas assez de recul pour voir si il
y a un gain. On peut supposer que l’on gagne au moins les calculs
concourants d’un même cache, qui n’ont plus lieu. Mais on perd aussi
une insertion SQL+un delete pour chaque calcul de cache en background.

Cédric

Le 31 oct. 2009 à 12:03, cedric.morin@yterium.com a écrit :

Je continue a améliorer la proposition :

Du côté du core, j’ai introduit dans la branche dev le patch suivant
(applicable aussi sur la branche stable)
http://trac.rezo.net/trac/spip/changeset/14703
qui permet une personnalisation de la fonction public_produire_dist

Un exemple (imparfait) est alors d’ajouter dans config/mes_options
(ou dans le fichier options d’un plugin) :

function public_produire_page($fond, $contexte, $use_cache,
$chemin_cache, $contexte_cache, $page, &$lastinclude, $connect=‹  ›){
// calcul differe du cache ?
if (is_array($page)
AND count($page)
AND defined(‹ _DIR_PLUGIN_QUEUE ›)

AND !$GLOBALS[‹ visiteur_session ›][‹ id_auteur ›]

) {
// on differe la maj du cache et on affiche le contenu du cache ce
coup ci encore
$where = is_null($contexte_cache)?« principal »:« inclure_page »;
job_queue_add(‹ public_produire_page ›,$c=« Calcul du cache $fond
[$where] »,array($fond, $contexte, $use_cache, $chemin_cache,
$contexte_cache, NULL, $lastinclude, $connect),«  »,TRUE);
gunzip_page(&$page); // decomprimer la page si besoin
spip_log($c,‹ cachedelai ›);
return $page;
}

include_spip(‹ public/assembler ›);
return public_produire_page_dist($fond, $contexte, $use_cache,
$chemin_cache, $contexte_cache, $page, $lastinclude, $connect);
}

Je dis que l’exemple est imparfait car avec cette fonction, si le
cache est calculé dans la queue par un cron exécuté depuis le privé,
les urls sont référencées par rapport à ecrire/, donc commencent par
un …/.
De même, dans ce cas l’en-tete est compressé car c’est le réglage
par défaut de ecrire/

C’est un cas d’école intéressant qui n’était pas prévu pour
job_queue, et il faut réflechir pour savoir si la queue doit prendre
en charge ce type de besoin ou pas.
Si oui il faudrait alors pouvoir préciser le contexte d’execution de
la queue (public/prive), et ensuite être capable de se placer dans
le même contexte.

Cédric

Le 30 oct. 2009 à 21:41, cedric.morin@yterium.com a écrit :

Le patch précédent était incorrect.
Voici une version testée qui semble correspondre à ce que tu vises.
Par curiosité je viens de le mettre en service sur SPIP-Contrib.


spip-zone@rezo.net - http://listes.rezo.net/mailman/listinfo/spip-zone


Nouveau! Découvrez le Windows phone Samsung Omnia II disponible chez SFR. Cliquez ici

Mes chiffres sont totalement faux, en fait mon plugin est en stand by j’avais oublié la table se vide après 2000 insertions automatiquement. Mais l’idée que je développe persiste.

benoit


From: benoit.aubert@hotmail.fr
To: spip-zone@rezo.net
Subject: RE: [SPIP Zone] optimisation du cache?
Date: Tue, 3 Nov 2009 17:48:18 +0100

Pour notre site (topspeed.com), avec le trafic et le nombre de caches qu’on a ça revient à plusieurs centaines d’insertions dans job_queue à la minute. Est-ce que le plugin job_queue pourra gérer une liste qui croit à ce rythme sans soucis? A l’heure ou je parle je suis en train de regarder et la table de mon plugin grossit de 10 à 30 lignes par seconde. Je viens de regarder une période complète de remplissage, on est monté à 3000 lignes environ, pour subittement redescendre à 0 (lancement du cron job). C’est effréné car on est en plein pic de traffic la, ce qui au passage ne se repère pas du tout sur la charge CPU du serveur. Notez qu’on a un grand cache car on souhaite servir le plus de pages possible à partir du cache (environ 55000 fichiers par dossier donc environ 900 000 fichiers cache au total).

Dans mon plugin je régle un cron qui tourne toutes les 90 secondes (en théorie, mais on a beaucoup de taches dans cron.php donc c’est un peu plus), et traite à chaque passage au maximum 300 lignes de la table avec un DISTINCT (rafraichissant donc jusqu’à 300 blocs différents de cache).

Ca amène à mon autre question: je m’assure aussi dans mon plugin qu’une fois une ligne traitée, tous ses doublons soient alors supprimés de la table, car entre le moment ou un cache expire et le moment ou on le rafraichit en tâche de fond, d’autres visiteurs insérent exactement la même ligne. Mon petit monitoring ci-dessus le montre bien. Les facteurs sont par exemple des blocs très visités, surtout si on souhaite les rafraichir relativement régulièrement (plusieurs fois par jour), et surtout des pages composées de beaucoup de blocs (je sais c’est pas recommandé). Et ca s’agrave si on a un mauvais concours de circonstances (genre une série de tâches qui monopolisent le cron quelques minutes).

Bref faire deux ou trois fois le même calcul de cache en quelques minutes c’est une perte de temps et de ressources, et dans mon système c’est tout simplement vital pour trouver un équilibre entre fréquence de lancement du cron et nombre de lignes traitées par lancement, le tout pour éviter que la table ne se remplisse plus rapidement qu’elle ne se vide. On a essayé de faire la vérification en amont (insérer dans la table uniquement si la ligne n’existe pas déjà), mais ce process se déroulait alors au moment ou on présente la page au visiteur, ce qui ne va pas dans l’esprit du plugin. Ainsi on a décidé de faire le distinct en aval (dans le cron job), et effacer tous les doublons à chaque construction. Le résultat est un rythme d’insertion très soutenu, et de grandes variations dans la taille de la table, mais au final on redescent toujours à 0 ou presque à la fin d’un cycle, ce qui assure un rafraichissement des caches conforme à la date de la visite alors qu’il est expiré + 2 minutes.

J’espère avoir bien expliqué mon idée et que le plugin cache cool s’y adaptera. Sinon je pense que je devrai le bricoler un peu pour qu’il supporte notre site.

Benoit.

Subject: Re: [SPIP Zone] optimisation du cache?
From: cedric.morin@yterium.com
Date: Sun, 1 Nov 2009 11:32:06 +0100
CC: spip-zone@rezo.net
To: benoit.aubert@hotmail.fr

Et finalement, cela donne
Cache Cool - SPIP-Contrib

Qui tourne en prod sur SPIP-Contrib et sur http://www.cuisine-libre.fr
Les petits bug du départ ont été résolus.

En terme de temps de réponse perceptible par le visiteur, je note un
gain significatif qui se traduit par une homogénéité du temps de
réponse rapide, correspondant au service rapide d’une page tout en
cache, et se ressent comme une rapidité générale du site et un confort
de navigation.
Cela vaut surtout si le site a suffisamment de trafic pour que
l’ensemble du cache soit toujours assez frais (et qui suppose que
l’espace alloué au cache soit assez gros pour pouvoir garder une copie
à peu près complète).

En terme de charge serveur, je n’ai pas assez de recul pour voir si il
y a un gain. On peut supposer que l’on gagne au moins les calculs
concourants d’un même cache, qui n’ont plus lieu. Mais on perd aussi
une insertion SQL+un delete pour chaque calcul de cache en background.

Cédric

Le 31 oct. 2009 à 12:03, cedric.morin@yterium.com a écrit :

Je continue a améliorer la proposition :

Du côté du core, j’ai introduit dans la branche dev le patch suivant
(applicable aussi sur la branche stable)
http://trac.rezo.net/trac/spip/changeset/14703
qui permet une personnalisation de la fonction public_produire_dist

Un exemple (imparfait) est alors d’ajouter dans config/mes_options
(ou dans le fichier options d’un plugin) :

function public_produire_page($fond, $contexte, $use_cache,
$chemin_cache, $contexte_cache, $page, &$lastinclude, $connect=‹  ›){
// calcul differe du cache ?
if (is_array($page)
AND count($page)
AND defined(‹ _DIR_PLUGIN_QUEUE ›)

AND !$GLOBALS[‹ visiteur_session ›][‹ id_auteur ›]

) {
// on differe la maj du cache et on affiche le contenu du cache ce
coup ci encore
$where = is_null($contexte_cache)?« principal »:« inclure_page »;
job_queue_add(‹ public_produire_page ›,$c=« Calcul du cache $fond
[$where] »,array($fond, $contexte, $use_cache, $chemin_cache,
$contexte_cache, NULL, $lastinclude, $connect),«  »,TRUE);
gunzip_page(&$page); // decomprimer la page si besoin
spip_log($c,‹ cachedelai ›);
return $page;
}

include_spip(‹ public/assembler ›);
return public_produire_page_dist($fond, $contexte, $use_cache,
$chemin_cache, $contexte_cache, $page, $lastinclude, $connect);
}

Je dis que l’exemple est imparfait car avec cette fonction, si le
cache est calculé dans la queue par un cron exécuté depuis le privé,
les urls sont référencées par rapport à ecrire/, donc commencent par
un …/.
De même, dans ce cas l’en-tete est compressé car c’est le réglage
par défaut de ecrire/

C’est un cas d’école intéressant qui n’était pas prévu pour
job_queue, et il faut réflechir pour savoir si la queue doit prendre
en charge ce type de besoin ou pas.
Si oui il faudrait alors pouvoir préciser le contexte d’execution de
la queue (public/prive), et ensuite être capable de se placer dans
le même contexte.

Cédric

Le 30 oct. 2009 à 21:41, cedric.morin@yterium.com a écrit :

Le patch précédent était incorrect.
Voici une version testée qui semble correspondre à ce que tu vises.
Par curiosité je viens de le mettre en service sur SPIP-Contrib.


spip-zone@rezo.net - http://listes.rezo.net/mailman/listinfo/spip-zone


Nouveau! Découvrez le Windows phone Samsung Omnia II disponible chez SFR. Cliquez ici


Nouveau! Découvrez le Windows phone Samsung Omnia II disponible chez SFR. Cliquez ici

Le 3 novembre 2009 17:48, Benoit Aubert <benoit.aubert@hotmail.fr> a écrit :

Pour notre site (topspeed.com), avec le trafic et le nombre de caches qu’on a ça revient à plusieurs centaines d’insertions dans job_queue à la minute. Est-ce que le plugin job_queue pourra gérer une liste qui croit à ce rythme sans soucis? A l’heure ou je parle je suis en train de regarder et la table de mon plugin grossit de 10 à 30 lignes par seconde. Je viens de regarder une période complète de remplissage, on est monté à 3000 lignes environ, pour subittement redescendre à 0 (lancement du cron job).

Le plugin job queue est encore jeune et n’a pas été testé dans ces conditions, c’est sûr.
Peut être va-t-il falloir augmenter dans ton cas le nombre de jobs qu’il a le droit de traiter en un coup.
Par contre, as-tu bien la balise #SPIP_CRON dans toutes tes pages ?

C’est effréné car on est en plein pic de traffic la, ce qui au passage ne se repère pas du tout sur la charge CPU du serveur. Notez qu’on a un grand cache car on souhaite servir le plus de pages possible à partir du cache (environ 55000 fichiers par dossier donc environ 900 000 fichiers cache au total).

OK

Dans mon plugin je régle un cron qui tourne toutes les 90 secondes (en théorie, mais on a beaucoup de taches dans cron.php donc c’est un peu plus), et traite à chaque passage au maximum 300 lignes de la table avec un DISTINCT (rafraichissant donc jusqu’à 300 blocs différents de cache).

Dans job queue, il tourne à la demande à chaque appel de #SPIP_CRON, donc potentiellement à chaque hit si besoin, sans attendre 90secondes.
Et la limite de 100 jobs à chaque fois parait du coup cohérente avec ce que tu avais.

Ca amène à mon autre question: je m’assure aussi dans mon plugin qu’une fois une ligne traitée, tous ses doublons soient alors supprimés de la table, car entre le moment ou un cache expire et le moment ou on le rafraichit en tâche de fond, d’autres visiteurs insérent exactement la même ligne. Mon petit monitoring ci-dessus le montre bien. Les facteurs sont par exemple des blocs très visités, surtout si on souhaite les rafraichir relativement régulièrement (plusieurs fois par jour), et surtout des pages composées de beaucoup de blocs (je sais c’est pas recommandé). Et ca s’agrave si on a un mauvais concours de circonstances (genre une série de tâches qui monopolisent le cron quelques minutes).

Avec job_queue, le problème est traité à la source :
cache_cool précise que la tache ne doit pas être doublonée, et si il y a un même job déja planifié (même fonction, mêmes arguments), il ne l’ajoute pas.

Bref faire deux ou trois fois le même calcul de cache en quelques minutes c’est une perte de temps et de ressources, et dans mon système c’est tout simplement vital pour trouver un équilibre entre fréquence de lancement du cron et nombre de lignes traitées par lancement, le tout pour éviter que la table ne se remplisse plus rapidement qu’elle ne se vide. On a essayé de faire la vérification en amont (insérer dans la table uniquement si la ligne n’existe pas déjà), mais ce process se déroulait alors au moment ou on présente la page au visiteur, ce qui ne va pas dans l’esprit du plugin. Ainsi on a décidé de faire le distinct en aval (dans le cron job), et effacer tous les doublons à chaque construction. Le résultat est un rythme d’insertion très soutenu, et de grandes variations dans la taille de la table, mais au final on redescent toujours à 0 ou presque à la fin d’un cycle, ce qui assure un rafraichissement des caches conforme à la date de la visite alors qu’il est expiré + 2 minutes.

J’espère avoir bien expliqué mon idée et que le plugin cache cool s’y adaptera. Sinon je pense que je devrai le bricoler un peu pour qu’il supporte notre site.

Toute la gestion de la queue est dans job_queue, donc c’est peut-être là qu’il va falloir faire quelques réglages.
Peut-être qu’il faudrait ajouter un watchdog dans cache-cool :
si le nombre de jobs de calcul de cache depasse une limite donnée on purge et on avertit le webmestre, pour maintenir la qualité de service autant que faire se peux.

Normalement, par conception, job_queue doit être capable de vider la queue plus rapidement et de façon plus continue que le cron a fréquence fixe, car si besoin il traite à chaque hit (donc il peut traiter potentiellement 100 caches à chaque hit), dans une limite de temps fixée à 50% de max_execution_time (donc 15s en général).

Je suis preneur de tout retour d’expérience sur ces 2 plugins !

Cédric