RobotsStats et PHP: Optimisation

sepang
WRInaute discret
WRInaute discret
 
Messages: 88
Inscription: 26 Jan 2003

RobotsStats et PHP: Optimisation

Message le Mar Jan 06, 2004 18:39

Hello,

Je préviens tout de suite: j'ai téléchargé la derniere version (me semble t-il) hier, peut etre que les remarques que je vais faire ont déja été faites. (non, je n'ai pas pris le temps de lire tt le forum)

Je voulais parler de Robotstats, et plus particuclièrement du coeur du programme, robotstats.inc.php. Son importance est bien supérieure aux autres scripts, car il est inclus dans toutes les pages du site (17 000 pages sur un de mes sites, par exemple), donc sa consommation est sensible. C'est un bon programme, je ne suis pas la pr remetttre en cause son efficacité, mais juste pour aider à son optimisation.

C'est pourquoi j'ai trouvé cette partie du code particulierement génante:

Code: Tout sélectionner
  // pour chaque robot (sauf ceux qui sont désactivés)
  $sql  = "SELECT *";
  $sql .= " FROM ".$RS_TABLE_ROBOTS;
  $sql .= " WHERE actif=1";
  $res  = mysql_query($sql) or sendErrorMySQL($sql);

  // tant qu'aucun robot n'a été détecté, et qu'il y en a à tester
  while ( !($detecte) && ($enr = @mysql_fetch_array($res)) )
  {
    // selon le mode de détection du robot :
    if ($enr["detection"] == $RS_DETECTION_USER_AGENT)
    {
      // on détecte le robot en regardant son User Agent
      $detecte = (stristr($_SERVER["HTTP_USER_AGENT"], $enr["user_agent"]));
    }
    else if ($enr["detection"] == $RS_DETECTION_IP)
    {
      // on détecte le robot par son adresse IP
      $detecte = false;
      if ($enr["ip1"] != "")
      {
        $detecte |= ( strstr(substr($_SERVER["REMOTE_ADDR"], 0, strlen($enr["ip1"])), $enr["ip1"]) !== false );
      }
      if ($enr["ip2"] != "")
      {
        $detecte |= ( strstr(substr($_SERVER["REMOTE_ADDR"], 0, strlen($enr["ip2"])), $enr["ip2"]) !== false );
      }

     //echo $_SERVER['REMOTE_ADDR'];
    }


Si on analyse, on cherche en fait dans la Bdd des enregistrements ACTIFS correspondant soit à l'IP si on détecte par l'ip (tester ip1 et ip2) soit au user agent, si on détecte.

Pour ca on liste tous les enregistrements de la base, et on compare avec des tests PHP.

Plusieurs pb: La méthode est très lourde, et très mauvaise. Lister tous les enregistrements pr les comparer un par un surcharge le serveur inutilement. (d'autant qu'on utilise meme pas les REGEXP)
En fait on surcharge mySQL des le départ avec un "SELECT (*)" à proscrire absolument. (voir toutes les docs mySQL).

Je propose donc de reconceptualiser ca simplement (ca a surement déja été fait, auquel cas dites le moi et j'effacerai mon msg) ;)

Donc on vire la boucle while (et meme tout le code posté au dessus), et à la place on a:

Code: Tout sélectionner
$sql = "SELECT id FROM ".$RS_TABLE_ROBOTS." WHERE actif=1 AND (user_agent = '".$_SERVER['user_agent']."' AND detection = 'detection_user_agent') OR ((ip1 LIKE '".$_SERVER['REMOTE_ADDR']."%' OR ip2 LIKE '".$_SERVER['REMOTE_ADDR']."%') AND detection = 'detection_ip')";

$myQuery = mysql_query($sql)OR sendErrorMySQL($sql);
$numRows = mysql_num_rows($myQuery);
$robotId = mysql_result($myQuery, 0, 'id');

    if ($numRows == 1)
    {
      // date, adresse IP du robot et nom de domaine
      $robot_ = $robotId;
      $date_  = date("Y-m-d H:i:s");
      $ip_    = $_SERVER["REMOTE_ADDR"];
      $dns_   = @gethostbyaddr($ip_);
      $code_  = $_SERVER["REDIRECT_STATUS"];

etc...


Et voila, plus aucun test PHP (cool, car on évite les pb de compatibilité des fonctions etc...), on fait une requete légere (car on récupere juste id), et on raccourci le code.


Deuxieme (petit) probleme:

Code: Tout sélectionner
      // récupération de l'URL (située après le nom de domaine)
      if ($RS_URL_REWRITING == 'y')
      {
        $url_ = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
      }
      else
      {

        $url_ = $_SERVER["SCRIPT_NAME"];
        if ($_SERVER["QUERY_STRING"] != "")
          $url_ .= "?".$_SERVER["QUERY_STRING"];
      }


Le probleme, c'est que $_SERVER['REQUEST_URI'] fait déja tout tout seul!
Ce code deviendra donc, simplement:

Code: Tout sélectionner
$url_ = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];



Voila, c'était la réaction "a chaud", d'un développeur PHP qui aime beaucoup ce site, et le travail que fait Olivier Duffez pour les Webmasters depuis déja pls années! ;)


WebRankInfo
Administrateur du site
Administrateur du site
 
Messages: 19420
Inscription: 19 Avr 2002

Message le Mar Jan 06, 2004 19:47

Un grand merci à toi, développeur PHP qui [...] ;-)
Je vais inclure ça dès que possible...


George Abitbol
WRInaute passionné
WRInaute passionné
 
Messages: 1923
Inscription: 6 Juin 2003

Message le Mar Jan 06, 2004 19:57

Puisqu'on est dans l'optimisation, autant utiliser mysql_fetch_row() (ou une de ses petites soeurs) au lieu de mysql_result(), non ?

Fred


mahefarivony
WRInaute accro
WRInaute accro
 
Messages: 11405
Inscription: 14 Oct 2002

Message le Mar Jan 06, 2004 20:49

powaaa! les cadors du php/mysql en pleine action.. super les gars ! :lol:

sepang
WRInaute discret
WRInaute discret
 
Messages: 88
Inscription: 26 Jan 2003

Message le Mar Jan 06, 2004 21:41

pas de quoi WRI ;)
Pour mysql_fetch_row(), c'est une fonction qu'on utilise jamais ds les gros projets... en effet, si jamais, comme ca arrive tres souvent, t'en viens à ajouter un champs en plein milieu de ta table, tu es mal...

exemple: table id | prenom | age
devient table id | prenom | nom | age

Si tu avais ca dans ton code:

Code: Tout sélectionner
$query = mysql_query("SELECT * from `table`"); //déconseillé d'ailleurs le *,lol
while ($row = mysql_fetch_row($query))
   $age = $row[2];


la ton $age te renverra le nom...

Bref tout ca pour dire qu'il vaut mieux utiliser mysql_fetch_array(), mais bon, pour une seule donnée comme ca, je vois pas en quoi l'utilisation de mysql_result() serait pénalisante. :roll: (à ne surtout pas utiliser pour récupérer 20 résultats, mais bon, pour UN seul, ca économise du code)

Mais bon sinon ce serait

Code: Tout sélectionner
$myQuery = ...
if ($myRow = mysql_fetch_array($myQuery))
   $robotId = $myRow['id']; // ou $myRow[0]; pr les inconditionnels du fetch_row ;)


Sinon, Olivier, je pensais, pr les prochaines versions à proposer un système d'archivage des statistiques, afin d'alléger la table log. Contacte moi sur mon mail si tu veux je pourrais essayer de m'y coller ;)

Tschuss
Sepang


George Abitbol
WRInaute passionné
WRInaute passionné
 
Messages: 1923
Inscription: 6 Juin 2003

Message le Mar Jan 06, 2004 22:37

sepang a écrit:pas de quoi WRI ;)
Pour mysql_fetch_row(), c'est une fonction qu'on utilise jamais ds les gros projets... en effet, si jamais, comme ca arrive tres souvent, t'en viens à ajouter un champs en plein milieu de ta table, tu es mal...


Oui, j'ai d'ailleurs précisé "ou une de ses soeurs" ;) Cela dit, le cas que tu évoques n'intervient que lors de l'utilisation de SELECT *, ce qui est à proscrire. Avec un SELECT champ1, champ2, etc., il ne se pose plus (l'indice du mysql_fetch_row() n'étant pas le rang du champ dans la table mais le rang du champ dans le SELECT).

Dans le cas présent, vu qu'on a un SELECT id, ça serait bon. Mais je chipote ;)

Fred


WebRankInfo
Administrateur du site
Administrateur du site
 
Messages: 19420
Inscription: 19 Avr 2002

Message le Mar Jan 06, 2004 22:39

promis, depuis quelque temps maintenant, je n'écris plus SELECT * dans mes scripts...

sepang
WRInaute discret
WRInaute discret
 
Messages: 88
Inscription: 26 Jan 2003

Message le Mar Jan 06, 2004 22:42

très juste Georges, on est d'accord ;)

fredsoft
WRInaute discret
WRInaute discret
 
Messages: 242
Inscription: 26 Jan 2003

Message le Dim Jan 11, 2004 17:26

petit complément en ce qui me concerne


$document_root en register globals = off ne fonctionne pas...il faut récupérer cela via $_SERVER..je comprends pas d'ailleur pourquoi dans certains cas c'est fait.

sinon pb avec GD je pense..message illégal pie plot....

bon soft semble t'il sinon..


Si vous avez aimé cette discussion, partagez-la sur vos réseaux sociaux préférés :

Lectures recommandées sur ce thème :



Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 0 invités