Help - Search - Member List - Calendar
Full Version: Mettre des parties en cache (reduit R-mysql)
IPBR-FR > Divers > Documentation > Soumettez vos astuces ou tutoriels
blc29
Cela permet de diminuer le nombre de requête et d'accélérer légérement votre forum car tant que la variable est mise en cache on n'execute plus les requêtes et le code pour créer cette variable

Mon forum est installé dans le repertoire forum

1- créer un répertoire du nom que vous voulez (par ex cachevariable)
où vous voulez (par exemple forum/cachevariable/)
ce répertoire contiendra les variables mises en cache
CHMOD du répertoire "777"


2- créer un fichier class.cacher.php contenant le code suivant
(ce code provient du site : http://www.phpclasses.org/ )
j'ai mis ce fichier dans forum/sources/lib/ mais ça n'a pas d'importance

CODE
<?
/**

class.cacher.php -- Class used to cache a variable in serialized form.

Written by Serge Stepanov (serge_AT_gfxcafe.com).
Feel free to email me with questions. If you find this useful, would be great to hear from you.

version 1.0 -

Changes:
- First release.

Notes:
- Get() method will only use
the first occurrence, after which
the loop will be broken.

Example:

include("class.cacher.php");

$cache = new Cacher;
// Get var if not 60 seconds old
$variable = $cache->Get("variable_with_id", 60);

if (!$variable) {
// Cache file expired or is inexistant
// Do something to get new data
$cache->Set("variable_with_id", $newdata);
$variable = $newdata;
}

echo $variable;
**/

class Cacher {
// Where things are cached to (must have trailing slash!)
var $cacheDir = "/tmp/";
// How long to cache something for in seconds, default 1hr
var $defaultCacheLife = "3600";

/**
Set($varId, $varValue) --
Creates a file named "cache.VARID.TIMESTAMP"
and fills it with the serialized value from $varValue.
If a cache file with the same varId exists, Delete()
will remove it.
**/
function Set($varId, $varValue) {
// Clean up old caches with same varId
$this->Delete($varId);
// Create new file
$fileHandler = fopen($this->cacheDir . "cache." . $varId . "." . time(), "a");
// Write serialized data
fwrite($fileHandler, serialize($varValue));
fclose($fileHandler);
}

/**
Get($varID, $cacheLife) --
Retrives the value inside a cache file
specified by $varID if the expiration time
(specified by $cacheLife) is not over.
If expired, returns FALSE
**/
function Get($varId, $cacheLife="") {
// Set default cache life
$cacheLife = (!empty($cacheLife)) ? $cacheLife : $this->defaultCacheLife;

/* Loop through the directory looking for cache file */
$dirHandler = dir($this->cacheDir);
while ($file = $dirHandler->read()) {
/* Check for cache file with requested varId */
if (preg_match("/cache.$varId.[0-9]/", $file)) {
$cacheFileName = explode(".", $file);
// Cache file creation time
$cacheFileLife = $cacheFileName[2];
// Full location
$cacheFile = $this->cacheDir . $file;

/* Check to see if cache file has expired or not */
if ((time() - $cacheFileLife) < $cacheLife) {
$fileHandler = fopen($cacheFile, "r");
$varValueResult = fread($fileHandler, filesize($cacheFile));
fclose($fileHandler);
// Still good, return unseralized data
return unserialize($varValueResult);
} else {
// Cache expired, break loop
break;
}
}
}
$dirHandler->close();
return FALSE;
}

/**
Delete($varId) --
Loops through the cache directory and
removes any cache files with the varId
specified in $varID
**/
function Delete($varId) {
$dirHandler = dir($this->cacheDir);
while ($file = $dirHandler->read()) {
if (preg_match("/cache.$varId.[0-9]/", $file)) {
unlink($this->cacheDir . $file); // Delete cache file
}
}
$dirHandler->close();
}

}

?>


il y a les deux variables suivantes à régler
var $cacheDir = "/tmp/";
-> Chemin du dossier où les variables sont mis en cache
J'ai mis un chemin absolu du type /home/www/....../cachevariable/ (vous le trouverez dans le PC admin du forum "System Settings " -> "General Configuration" -> "Board Server Paths" pour être utilisé par d'autres applications

var $defaultCacheLife = "3600";
Durée du cache par défaut


3- mettre en cache le bloc de statistique du forum :
vu que ces infos ne sont pas obligatoirement à jour à la minute on peut les mettre en cache (moi j'ai mis 3min)

ouvrez le fichier sources/Boards.php

la variable à mettre en cache se nomme $stats_html

recherchez
CODE
$stats_html = "";


et ajoutez avant
CODE
require("sources/lib/class.cacher.php");

$cache = new Cacher;
$variable1 = $cache->Get('stat1', 180); // 180 -> 3 min
if (!$variable1) {


puis recherchez
CODE
 if ($stats_html != "")
 {
  $this->output .= $this->html->stats_header();
  $this->output .= $stats_html;
  $this->output .= $this->html->stats_footer();
 }


remplacez par
CODE
 if ($stataffiche != "")
 {
  $this->output .= $this->html->stats_header();
  //$this->output .= $stats_html;
  $this->output .= $stataffiche;
  $this->output .= $this->html->stats_footer();
 }


et ajoutez au dessus
CODE
   $cache->Set('stat1', $stats_html);
   $variable1 = $stats_html;
}
$stataffiche =  $variable1;


ATTENTION : si vous mettez d'autres choses en cache n'oubliez pas de modifier id de la variable : $variable1 = $cache->Get('stat1', 180);
ici stat1

4- mettre en cache des blocs du portail myibportal
ce portail utilise la variable $data pour les blocs en php utilisant une template
cette variable contient le code du corp du bloc

mon portail est installé dans le repertoire portal

a- tout d'abord il faut inclure la classe sur l'index du forum
ouvrir le fichier portal/index.php

rajoutez aprés
CODE
require_once("mainfile.php");

CODE
require("../forum/sources/lib/class.cacher.php");

chemin relatif vers la classe de cache

b- il ne reste plus qu'a choisir les blocs qu'on veut mettre en cache

ATTENTION: ne pas mettre des blocs qui sont relatifs à un utilisateur en particulier car le cache est commun à tout le monde donc pas le bloc navigation, info du membre, ...

prenons par exemple le bloc top5 des posteurs
ne variant pas souvent mais il utilise une requête

CODE

$numberofposters = 5;

$query = $DB->query( "SELECT * FROM ibf_members WHERE `posts` > 0 ORDER BY `posts` DESC LIMIT 0,".$numberofposters);

$rating = 0;

$data = "<table>";
while( $row = $DB->fetch_row($query) ) {
$rating++;
$data.=top_posters_row($row+array("rating"=>$rating));
}
$data .="</table>";

function top_posters_row($posterdata) {
global $ibforums;
$buildrow = "<tr>";
$buildrow .="<td class='forum2' width='80%'>{$posterdata['rating']}. <a href='{$ibforums->vars['board_url']}/index.{$ibforums->vars['php_ext']}?s={$ibforums->session_id}&act=Profile&CODE=03&MID={$posterdata['id']}'>{$posterdata['name']}</a></td>";
$buildrow .="<td class='forum2' width='20%' align='right'>{$posterdata['posts']}</td>";
$buildrow .="</tr>";
return $buildrow;
}

dans le principe c'est la variable $data qui est affiché dans le bloc (template)
donc c'est cette varible qu'il faut mettre en cache

ce qui donne
CODE
$cache = new Cacher;
$variable = $cache->Get('topmes1', 3600);

if (!$variable) {
// Cache file expired or is inexistant
// Do something to get new data
$numberofposters = 5;

$query = $DB->query( "SELECT * FROM ibf_members WHERE `posts` > 0 ORDER BY `posts` DESC LIMIT 0,".$numberofposters);

$rating = 0;
$newdata = "<table>";
while( $row = $DB->fetch_row($query) ) {
$rating++;
$newdata.=top_posters_row($row+array("rating"=>$rating));
}
$newdata .="</table>";
$cache->Set('topmes1', $newdata);
$variable = $newdata;
}
else {
$variable= "<!-- Cache -->".$variable."<!-- /Cache -->";
}
$data = $variable;

function top_posters_row($posterdata) {
global $ibforums;
$buildrow = "<tr>";
$buildrow .="<td class='forum2' width='80%'>{$posterdata['rating']}. <a href='{$ibforums->vars['board_url']}/index.{$ibforums->vars['php_ext']}?s={$ibforums->session_id}&act=Profile&CODE=03&MID={$posterdata['id']}'>{$posterdata['name']}</a></td>";
$buildrow .="<td class='forum2' width='20%' align='right'>{$posterdata['posts']}</td>";
$buildrow .="</tr>";
return $buildrow;
}



dans cette exemple le temps du cache est une heure
j'ai remplacé la variable $data par $newdata c'est qu'a la fin du code qu'on utilise la variable $data (ou celle en cache ou celle calculée)

ATTENTION : comme précédemment ne reutilisez pas une id de varaible 2 fois ici 'topmes1' et non plus stat1 qui est utilisé pour le bloc de stat du forum

Ouf je crois que j'ai tout dit smile.gif
n'hésitez pas à me faire des remarques
ou si vous pensez à une autre partie du forum à mettre en cache car je ne vois pas d'autre partie ou cela peut être utilisé

Edit by Fabien: Merci d'utiliser la balise codebox pour les morceaux de code long afin de ne pas déformer le skin.
David
tu as gagné combien en temps d'execution ??? combien as tu perdu de requetes sur ton portail?

Merci smile.gif
blc29
fais un tour sur ce sujet
http://ipb2.ipbr-fr.com/http://ipb2.ipbr-fr.com/index.php?showtopic=446
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2012 Invision Power Services, Inc.