Page 1 sur 1

Sauvegarde des instances d'objets en session

Posté : 17 août 2006, 18:23
par Ouaibou
Bonsoir,

J'ai lu dans un livre dédié à PHP que l'instancification d'un d'objet prenait du temps. Logique me diriez vous :roll:. Bref alors pourquoi ne pas stocker l'instance des objets créés en session ou dans un fichier, lui même stocké sur un serveur.

A partir de là, je me suis lancé il y a tout juste quelques minutes à faire une petite classe afin d'enregistrer les instances en session.

Ca a été écrit vite fait, j'ai pas encore testé si ça fonctionné, ni rien de rien, etc. Vous allez donc vous demander pourquoi je vous parles ?
En fait j'aurais aimé avoir votre avis pour savoir si cette manière de faire était utile et correct : es-ce que en faisant ainsi, on pourra noter un certain gains de temps d'éxécution ? (oui j'ai pas fait de bench non plus :s) Es-ce que vous vous y prennez d'une autre façon pour sauvegarder vos objets ?

Si oui, utilisez vous un fichier texte à la place ou vous stockez à l'intérieur l'instance de vos objets après les avoir sérializés ? Ou bien autre chose ?

Dans le cas contraire et même si dans le cas pas contraire (si c'est possible car j'aimerais pas mourir bête :D), es-ce qu'il est nécessaire de sérializer les objets qu'on veut passer en session ? (il me semble que c'est fait automatiquement, mais j'ai un gros doute :shock: car j'ai eu du mal à retrouver une information sur ça).
<?php
	class InstanceManager 
	{
		private $instance; // Tableau contenant les instances a sauvegarder en session

		/**
		 * Constructeur
		 */
		
		public function __construct()
		{
			$_SESSION['instance'] = array();
			$this->instance =& $_SESSION['instance'];
		}
		
		/**
		 * @param $class Nom de la classe dont on veut sauvegarder 
		 * son instance en session.
		 * @param $param Parametre du constructeur de la classe passee
		 * en parametre (A ameliorer pour prendre en charge multi param...).
		 */
		
		public function add($class, $param=null)
		{
			if(!isset($this->instance[$class]))
			{		
				$this->instance[$class] =& new $class($param);
			}
		}
		
		/**
		 * @param $class Nom de la classe dont on veut recuperer l\'instance.
		 * @return Renvoi l\'instance de la classe demandee si elle existe,
		 * false dans le cas contraire.
		 */
		
		public function getInstanceOf($class)
		{
			$instanceOfClass = $this->instance[$class];
		
			if(isset($instanceOfClass))
			{		
				return $instanceOfClass;
			}
			else
			{
				return false;
			}
		}
	}
?>
Merci d'avance :wink:

@+

Posté : 17 août 2006, 18:47
par katagoto
Je pense qu'un gain de quelques millième de secondes serais constater sur de petits sites mais pour les gros site je pense que ça serai plus pénible pour le programmeur au niveau de la sérialization moi j'utilise les fichiers textes pour les fonctions après les avoir sérialisé c'est plus pratique !!!

Posté : 17 août 2006, 20:08
par jeff
salut

pour ma part les sessions ont une utilisation bien definie a savoir stocké des informations pour un utilisateur de facon temporaire

si ton instance est utilisé un grand nombre de fois, au lieu de recreer un objet nouveau, tu peut utilisé un singleton.
si tu a des objets similaire tu peu les clonnés

pour ce qui est du gain de temps je pense qu'il est minime, sur tout si tes session sont stocké en base de donnée.

pour la serializtion, ou les objet comme toutes autres variable sont serializé avant d'etre mis en session

Posté : 17 août 2006, 20:51
par rami
salut
si ton instance est utilisé un grand nombre de fois, au lieu de recreer un objet nouveau, tu peut utilisé un singleton.
L'utilisation d'un singleton ne changera rien puisqu'à chaque nouvelle requête il sera créé.

Je ne suis pas certain de l'utilité de sérialiser des objets. Ce genre de soucis n'intervient que sur des sites à fort traffic. De plus, je ne suis pas certain que sérialiser / désérialiser un objet soit plus rapide que de l'instancier, sauf si le constructeur fait des traitements lourds.

Si tu rencontres des problèmes de performance, installe un cache d'opcode, ca augmentera fortement les performances de PHP.

Posté : 17 août 2006, 20:56
par jeff
L'utilisation d'un singleton ne changera rien puisqu'à chaque nouvelle requête il sera créé.
je donnais cette solution dans le cas ou cette objet est utilisé plusieur fois dans l'execution d'un script ( comme pour requeter une base de donné)

Posté : 18 août 2006, 10:40
par Ouaibou
Jeff > En fait le singleton ne raisoudra aucunement le problème. Comme a dit rami, à chaque requête l'objet sera recréé.
De plus, je ne suis pas certain que sérialiser / désérialiser un objet soit plus rapide que de l'instancier, sauf si le constructeur fait des traitements lourds.
Rami > Effectivement ç'est un peu la question que je me pose, es-ce que faire tout un tralala sérializer, désérializer, stocker, déstocker, ne prendrait pas plus de temps qu'instancifier un nouvel objet. Faudrait que je trouve des benchs ou que j'en fasse.

Pour le cache d'opcode c'est pas possible pour le moment, je suis sur un mutualisé.

Une autre solution serait peut être de faire un peu comme katagoto, utiliser un fichier.

Je vais essayé de faire quelques tests cette après-midi et je vous tiens au courant.

Merci pour vos réponses.

Si certains ont d'autres idées je suis preneur :D

@+

Posté : 19 août 2006, 00:14
par Ouaibou
Oplà de retour :wink:

Donc je viens de faire quelques tests en me basant sur le temps d'éxécution pour instancifier 5 objets (oui c'est pas énorme mais apparemment c'est suffisant :roll:) :

Instancification classique : ~0.09157 s

Instancification en utilisant la classe InstanceManager :
- premier passage (instancification de l'objet instanceManager) : ~0.09183 s
- autres passages : ~0.13642 s
<?php
	include_once('class/InstanceManager.class.php');
	
	include_once('class/Database.class.php');
	include_once('class/Auth.class.php');
	include_once('class/Date.class.php');
	include_once('class/Crypt.class.php');
	
	$debut = explode(" ", microtime());
	$debut = $debut[1] + $debut[0];

	if(!isset($_SESSION['instanceManager']))
	{
		$_SESSION['instanceManager'] = new InstanceManager();
	}
	
	$instanceManager = $_SESSION['instanceManager'];
	
	$instanceManager->add('Database');
	$db = $instanceManager->getInstanceOf('Database');
	
	$instanceManager->add('Auth', $db);
	$auth = $instanceManager->getInstanceOf('Auth');
	
	$instanceManager->add('Crypt');
	$crypt = $instanceManager->getInstanceOf('Crypt');	

	$instanceManager->add('Date');
	$date = $instanceManager->getInstanceOf('Date');	

	$fin = explode(" ", microtime());
	$fin = $fin[1] + $fin[0];
	
	$temps_passe = $fin - $debut;
	
	echo "Temps d'execution : ".($temps_passe)." s <br />";
?> 
Bref ç'est pas une bonne idée de stocker les instances d'objets en session. Comment faire mieux ? :lol:

@+

Posté : 21 août 2006, 22:39
par rami
Les instancier à chaque nouvelle requête :D

Je ne connais pas d'autres moyens.

Posté : 21 août 2006, 23:55
par zigz4g
Salut.

Je suis du même avis que Rami. Il ne faut pas rentrer dans le mode je fais tout en optimisant et je pense gagner des millisecondes.
La solution proposée avec les sessions me parait être mauvaise. Tout d'abord le script doit s'initialiser se qui prend du temps mais après il doit aussi faire la gestion des sessions. Les sessions étant dans la plupart des cas dans des fichiers, il devient évident que la lecture et l'ecriture prend des ressources.
Parfois il est plus rapide de laisser faire le code normallement car a priori et je l'espere les développeurs de PHP font de l'optimisation. Ou tout du moins font en sorte que l'on n'est pas des boucles de traitements trop longues.

La meilleure solution est normellement les accélérateurs de opcode qui enleveront le temps qu'il faut pour le moteur de PHP pour créer les objets et autres partie du code. Dans le cas des sessions je ne penses pas que les accélérateurs puissent bien les gérer.

Pour ce qui est du problème de base, parfois il faut savoir mettre la main au porte monnaie si vraiment ton site te parraît lent. Les solutions sont multiples, serveurs dédiés ou mutualisés avec accélérateurs, meilleurs serveurs avec plus de processeurs et de ram. Bien sur le cout est forcement plus cher mais on a rien sans rien :)