Les scripts à jéjé: Partage de la mémoire en php

Consultez la formation à Google Analytics de WebRankInfo / Ranking Metrics


fandecine
Modérateur
Modérateur
 
Messages: 1627
Inscription: Sam Avr 02, 2005 14:58

Les scripts à jéjé: Partage de la mémoire en php

Message le Jeu Mai 26, 2005 9:32

Me voici de retour avec un autre script. Cette fois-ci, il s'agit de trouver une alternative aux cookies et aux variables de session pour stocker des informations relatives à un visiteur de votre site.

Les cookies s'acquitent généralement bien de cette tache, encore faut-il que votre visiteur les accepte (20% de mes visiteurs n'acceptent pas les cookies!)

Les variables de session sont également un bon moyen de conserver des variables d'une page à l'autre mais présentent deux inconvegnants:
- le nombre de sessions n'est pas ilimité
- le passage de variables de session dans l'url peut avoir de graves incidence sur la prise en compte de vos pages par les moteurs de recherche http://www.webrankinfo.com/analyses/php/sessions.php

php nous fournis une alternative avec la possibilité de créer des blocks mémoire partagées accessible à tout les script fonctionnant sur le serveur(gestion des droit d'accés identique à la gestion des droits d'accés fichier linux) grace à un identifiant.

L'exemple dont je donne les sources permet de stocker dans un file de 50 enregistrement, l'ip d'un visiteur et d'y assoicier une valeur de 0 à 9. Le timestamp correspondant à la date/heure de création ou de mise ajour de la valeur est également stocké ce qui permet de faire tourner la file de façon à ce que lorsque les 50 enregistrements sont utilisés, on écrase le plus ancien. (une manère pour obtenir dans un espace fini une capacité pseudo infinie de stockage si on la rapproche à la durée de vie de l'information)

Attention: c'est un exemple pour expliquer le mécanisme! à vous d'immaginer comment utiliser cette fonctionnalité.

Par exemple, sur le site de mon profil, je gere 4 onglets en DHTML sur la page d'accueil. Ce mécanisme me permet de mémoriser sur quel onglet de la page d'accueil était le visiteur afin de restituer le contenu de cet l'onglet lorsque l'internaute:
- revient sur page d'accueil
- utilise les bouton prec et suiv de son navigateur

Les autres utilisations étant disons... plus stratégiques, je n'en parlerais pas ici :wink: Mais je sais que les wrinautes ont beaucoup d'idées!

ce script permet d'initialiser le block de mémoire partagé:
Code: Tout sélectionner
<?php
         $enre=time()."-xxxx.xxxx.xxxx.xxxx-x"; //on génére la chaine de caractères par défaut
         $mem=""; // on initialise la variable mémoire
         for($i=0;$i<50;$i++) { // on initilise la variable mémoire avec 50 enregistrements
            $mem.=$enre;
            if($i!=49) $mem.=";"; // on sépare chaque enregistrement par le car ";" sauf en fin de mémoire
         }
         $shm_id = @shmop_open(0xf00, "c", 0644, strlen($mem)); // création du block mémoire partagé
         if(!$shm_id) {  // on vérifie si la créatioon du block mémoire partagé a réussi
            echo "<div align=center>Erreur: Impossible de créer la mémoire partagée.</div><br>";
         } else {
            
            $shm_bytes_written = @shmop_write($shm_id, $mem, 0); // Ecriture dans le block de mémoire partagée
            echo "<div align=center>Création de la mémoire partagée.</div><br>";
         }

?>


celui-ci permet de détruire le block de mémoire partagée et libère la mémoire!
Code: Tout sélectionner
<?php
      $shm_id = @shmop_open(0xf00, "w", 0, 0); // création d'un handle pour notre block mémoire
      shmop_delete($shm_id); // destruction du block mémoire partagée
      echo 'block mémoire detruit';

?>

enfin, le script suivant permet de lire ( appel sans parametre dans l'url) ou d'écrire une valeur dans le bloc de mémoire partagée (appel avec le parametre Val=votrevaleur dans l'url methode GET):

Code: Tout sélectionner
<?php
      if(isset($_GET['Val'])) $Val=$_GET['Val']; //on récupére la valeur à écrire dans le block mémoire si elle existe
      $shm_id = @shmop_open(0xf00, "w", 0, 0); // on crée un handle pour acceder à notre block mémoire partagé
      if ($shm_id) {                // le block mémoire partagé existe
         $ok=sem_get (0xf00);       // demande de lecture du block mémoire partagée puis interdit l'acces au block mémoire partagé
         if(sem_acquire ($ok)) {     // l'accés au block mémoire est authorisé
            $shm_size=@shmop_size ($shm_id); // lecture de la taille du block mémoire partagée
            $tmp=substr(@shmop_read($shm_id, 0, $shm_size),0,16499); // lecture du block mémoire partagée
            $tab=split(";",$tmp); // création d'un tableau d'enregistrement à partir du block mémoire partégée
            $trouve=false;
            $mem=array();
            for($i=0;$i<50;$i++) {  // on récupére nos valeur du bloc mémoire partagé dans un tableau
               $val=split('-',$tab[$i]);
               $Enre=array ('time' => $val[0], 'ip' => $val[1], 'value' => $val[2]);
               $mem[$i]=$Enre;
               if(str_replace('*','',$Enre['ip'])==trim($_SERVER['REMOTE_ADDR'])) {  // on recherche si l'ip de l'internaute existe déjà
                  $trouve=true;  // l'ip existe
                  $mem[$i]['time']=time(); // on met la date à jour
                  if(isset($_GET['Val'])) $mem[$i]['value']=$Val; // si valeur passée en paramétre, on la stocke
                  $memvalue=$mem[$i]['value']; // on lit la valeur correspondant à l'ip de l'internaute
               }
            }
            sort($mem); // on trie notre tableau par date d'ancienneté
            if(!$trouve) {  // l'ip de l'internaute n'existe pas
               $mem[0]['time']=time(); // on stocke la date actuelle
               $mem[0]['ip']=trim($_SERVER['REMOTE_ADDR']); // on stocke l'ip de l'internaute
               if(isset($_GET['Val'])) $mem[0]['value']=$Val; else $mem[0]['value']=1; // ons stocke la valeur passée en paramètre ou 1 par défaut
               $memvalue=$mem[0]['value']; // on récupére la valeur associée à l'ip
            }
            $memwrite=""; // initialise une chaine vide
            for($i=0;$i<50;$i++) { // on reconstitue une chaine avec nos 50 enregistrements
               $memwrite.=$mem[$i]['time'].'-'.str_pad($mem[$i]['ip'],15,'*',STR_PAD_RIGHT).'-'.substr($mem[$i]['value'],0,1); // l'ip est complétée par "*" pour atteindre 15 caractères
               if($i!=$memsize-1) $memwrite.=';';
            }
            $shm_bytes_written = @shmop_write($shm_id, $memwrite, 0); // sauvegarde le block memoire partagé
            sem_release($ok);// autorise la lecture du block mémoire partagée
         }
      }
      echo $memvalue; // on affiche la valeur 'associée à l'ip de l'internaute
      exit(); // fin du script?>


Voila! J'utilise la mémoire partagée pour de nombreuses taches sur mes sites et cela fonctionne trés bien en consommant peu de ressources!

shrom
WRInaute passionné
WRInaute passionné
 
Messages: 865
Inscription: Lun Juil 05, 2004 22:37

Message le Jeu Mai 26, 2005 9:48

Juste 2 remarques:

1) l'identifiant est dans ce cas l'adresse IP du visiteur: dangereux si on a des visiteurs venant de AOL, Tiscali ... qui on la même IP à cause des proxy

2) la mémoire partagée n'est pas une alternative aux sessions, mais un autre moyen de stocker des informations.


fandecine
Modérateur
Modérateur
 
Messages: 1627
Inscription: Sam Avr 02, 2005 14:58

Message le Jeu Mai 26, 2005 9:55

shrom a écrit:Juste 2 remarques:

1) l'identifiant est dans ce cas l'adresse IP du visiteur: dangereux si on a des visiteurs venant de AOL, Tiscali ... qui on la même IP à cause des proxy

2) la mémoire partagée n'est pas une alternative aux sessions, mais un autre moyen de stocker des informations.


Comme je le précise dans le post, ce n'est qu'un exemple! De plus le danger dépends des donnnées stockées (lorsque c'est juste le contexte d'une page, c'est pas grave)

Enfin, je précise bien qu'il existe d'autres moyens, dont les session, en renvoyant à un article sur les problèmes engendrés par les variables de session passées dans l'url.

shrom
WRInaute passionné
WRInaute passionné
 
Messages: 865
Inscription: Lun Juil 05, 2004 22:37

Message le Jeu Mai 26, 2005 9:59

fandecine a écrit:Comme je le précise dans le post, ce n'est qu'un exemple! De plus le danger dépends des donnnées stockées (lorsque c'est juste le contexte d'une page, c'est pas grave)


Ben si ton application mélange les données entre tous les utilisateurs AOL parce qu'ils ont la même IP, c'est quand même génant

D'ailleurs, le stockage en mémoire partagée peut très bien être utilisé avec les sessions.


fandecine
Modérateur
Modérateur
 
Messages: 1627
Inscription: Sam Avr 02, 2005 14:58

Message le Jeu Mai 26, 2005 10:13

ok shrom! L'exemple choisi n'est pas top! Mais le seul objectif de ce post et d'expliquer le mécanisme de mémoire partagé, c'est tout!


itsme
WRInaute passionné
WRInaute passionné
 
Messages: 739
Inscription: Mer Oct 13, 2004 14:13

Message le Jeu Mai 26, 2005 10:51

Me voici de retour avec un autre script. Cette fois-ci, il s'agit de trouver une alternative aux cookies et aux variables de session pour stocker des informations relatives à un visiteur de votre site.


C'est effectivement une technique peu connue (et peu utilisee) mais ce n'est qu'une technique de stockage parmis d'autres (base, fichier)...

... et en aucun cas une alternative.

Il ne faut pas confondre moyens et objectifs ;)

taybott
WRInaute occasionnel
WRInaute occasionnel
 
Messages: 170
Inscription: Mer Jan 12, 2005 15:54

Message le Jeu Mai 26, 2005 11:05

Je connaissais pas cet technique (encore bcp de choses a apprendre :roll: ) mais je crois qu'il y a des situations où ça peut être plus pratique d'utiliser ça!!

Tex
WRInaute impliqué
WRInaute impliqué
 
Messages: 447
Inscription: Ven Juil 09, 2004 11:17

Message le Jeu Mai 26, 2005 11:07

le principal interet de la memoire partagée c'est de stocker des resultats de requetes ou des generations lourdes pour fournir un systeme de cache sans accés disque/bdd et donc instantané.

bravo a fandecine pour son exemple démonstratif, meme si pour stocker de simples variables les sessions restent quand meme la meilleure solution (bien evidemment il est preferable de les désactiver au passage des bots pour le referencement), mais le but ici etait de faire du proof of concept :)


Suede
WRInaute accro
WRInaute accro
 
Messages: 3721
Inscription: Ven Oct 04, 2002 11:22

Message le Jeu Mai 26, 2005 12:15

Juste une question :
Dans ton cas, tu utilises l'IP pour identifier à quel visiteurs appartient la pile. Comme dit précédemment, l'IP n'est pas forcément une bonne méthode donc il faudra un autre identifiant pour identifier ton visiteur. Par exemple, un identifiant de session...
amha ta méthode est plutot complementaire des sessions pour stocker des données que tu ne peux peut-etre pas stocker avec les identifiants de sessions (?).

François


fandecine
Modérateur
Modérateur
 
Messages: 1627
Inscription: Sam Avr 02, 2005 14:58

Message le Jeu Mai 26, 2005 13:04

En fait, je crois que j'ai vraiment mal choisi l'exemple, mais je pouvais pas faire trop long!

Tous les exemples que vous donnez sont valables bien entendu.

Mais, maintenent, imaginez que vous souhaitez afficher sur une page d'un annuaire, le nombre de visite d'un site. La solution classique (requette Mysql sur la BDD) présente deux inconvegnants:
- consommation de ressources
- rends innopérant et innutile la mise en cache de la pages (voir mon premier script)

Par conte, vous pouvez creer un tableau en memoire partage avec l'id du lien et le nombre de fois qu'il a été cliqué. C'est rapide et econnome en ressources et vous permet de mettre la page en cache. Ensuite, il suffit de faire un cron qui une fois/jour consolide votre BDD avec les resultats de la mémoire partagés et reinitialise la mémoire partagée.


ti_ouf
WRInaute occasionnel
WRInaute occasionnel
 
Messages: 189
Inscription: Dim Avr 10, 2005 12:58

Message le Jeu Mai 26, 2005 18:27

Etant donné que tu l'utilises pour palier aux cookies, utilises tu l'ip alors?

pedouille
WRInaute discret
WRInaute discret
 
Messages: 85
Inscription: Mar Mai 24, 2005 6:43

Message le Jeu Mai 26, 2005 18:42

Je trouve que c'est un bon moyen de se passer des sessions et des cookies. Il a déjà bien maché le travail, il reste à trouver un moyen d'identifier un utilisateur de façon unique. On pourrait imaginer un algorithme qui ne se base pas uniquement sur l'adresse ip, mais sur d'autres paramètres pour identifier de façon stable.

Sinon, il faudrait également mettre toute la soupe dans une belle classe, avec des fonctions simples de lecture / écriture, et là, je crois que tu tiens une bonne alternative.

ZBoy
Nouveau WRInaute
 
Messages: 1
Inscription: Ven Sep 07, 2007 18:18

Message le Ven Sep 07, 2007 18:32

Salut à tous,

Je viens de découvrir ce post car je cherchais le meilleur moyen de mettre à disposition des données partagées à tous mes visiteurs. En fait, je suis en train de créer un jeu en PHP, et je trouvais ça lourd que chaque utilisateur lance l'instanciation redondante de tous les objets utiles ( l' écran de jeu, les ennemis, les autres joueurs, les objets au sols, etc...) alors que ce sont les MEMES pour tous les joueurs qui se trouvent au meme endroit.

J'avais pensé d'abord à la méthodes qui consiste à fixer un identifiant de session choisi (qui devient par là une session commune) et d'y enregistrer mes objets/variables: inconvénient je pense la mémoire vive utilisée puis apparemment aussi un mécanisme de blocage de session par PHP au bout d'un moment. Bref

Pour l'instant j'étais parti sur du cache en XML de mes objets, l'affichage de données reviendrai à afficher ces XML, la modification de données à mettre à jour la base de données puis dans la foulée le/les fichiers de cache concernés.

Ca me paraissait pas trop mal niveau performance PHP et MySQL, mais cette discussion m'a vraiment interpelé je ne connaissait vraiment pas ce système : les données sont donc bien sur le disque et pas en mémoire vive? Dans ce cas là, la lecture/ecriture dans ce/ces fichiers n'est-t-elle pas nettement plus lente que l'accès à la base? Et enfin (!), y'a-t-il une restriction dans Apache pour cette option où serait-ele active sur n'importe quel hébergement PHP?

C'était long! Merci d'avance!

ZBoy


Formation recommandée sur ce thème :

Formation Google Analytics : en 2 jours, apprenez comment exploiter l'essentiel des possibilités de l'outil de mesure d'audience de Google. Formation animée par Julien Coquet, expert certifié officiellement par Google Analytics.

Tous les détails sur le site Ranking Metrics : programme, prix, dates et lieux, inscription en ligne.

Lectures recommandées sur ce thème :



Qui est en ligne

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