IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Arborescence / Tree - fuite de mémoire


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Juillet 2003
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Juillet 2003
    Messages : 15
    Par défaut Arborescence / Tree - fuite de mémoire
    Bonjour,

    Voici mon problème : je dois gérer plusieurs arborescences au cours de mon script, une arborescence par itération.
    Mon arborescence, c'est simplement une classe qui gère une relation parent-enfants.
    Mon problème est qu'à chaque itération, la mémoire utilisé par PHP augmente. Je pense que mon arborescence n'est pas supprimé de la mémoire à cause de cette relation entre objets.

    Je cherche donc un moyen de "vider" ma mémoire à chaque tour de boucle, ou une méthode pour mieux gérer mes arborescences (peut être utiliser un simple tableau de valeurs, donc sans relation entre objets ?).

    Voici un exemple de script en cause :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    $myProgam = new MyProgram();
     
    class MyProgram
    {
    	public function __construct()
    	{
    		for($i=0;$i<10;$i++)
    		{
    			$memory = round((memory_get_usage(true) / 1048576),5)." Mo";
    			$this->createTree();
    			echo $memory."<br>";	
    		}
    	}
     
     	/**
    	 * Théoriquement, la mémoire devrait se vider à la sortie de cette fonction,
    	 * mais ce n'est pas le cas !
    	 */     
    	public function createTree()
    	{
    		$tree = new Tree();	
    	}
    }
     
    class Tree 
    {
    	public $tree;
    	public function __construct()
    	{
    		$root = new Node();
    		$this->tree = $root;
    		for($i=0;$i<10;$i++)
    		{
    			$node = new Node();
    			for($cpt=0;$cpt<1000;$cpt++)
    			{
    				$node2 = new Node();	
    				$node2->parent = $node;
    				$node->children[] = $node;
    			}
     
    			$node->parent = $root;
    			$root->children[] = $node;
    		}				
    	}
    }
     
    class Node
    {
    	public $parent;
    	public $children = array();
    	public $value;
     
    	public function __construct()
    	{
    		$this->value = "------------------------------------------------------------------";	
    	}
    }
    Résultat :

    0.25 Mo
    0.75 Mo
    1.25 Mo
    1.75 Mo
    2.25 Mo
    2.75 Mo
    3.25 Mo
    3.75 Mo
    4.25 Mo
    4.75 Mo

    Merci

  2. #2
    Expert confirmé
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 694
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 694
    Par défaut
    essaye de mettre un destructeur à la classe Node pour voir s'il est bien appelé

  3. #3
    Membre averti
    Inscrit en
    Juillet 2003
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Juillet 2003
    Messages : 15
    Par défaut
    Citation Envoyé par mathieu Voir le message
    essaye de mettre un destructeur à la classe Node pour voir s'il est bien appelé
    j'ai ajouté la méthode __destruct() avec un echo et ça passe bien à l'intérieur.

    Après quelques recherches, je suis tombé sur des articles qui traitent de ce problème :

    http://paul-m-jones.com/blog/?p=262
    http://www.alexatnet.com/node/73

    En résumé, ce serait un problème PHP (à cause de références cycliques). Cela devrait être corrigé dans la version 5.3.
    Sur la page d'accueil de php.net, on a bien le :
    "Optional garbage collection for cyclic references" en nouveauté....

    J'ai également testé des modifications sur le programme précédent (avec l'aide du premier lien), et cela semble fonctionner :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
     
    $myProgam = new MyProgram();
     
    class MyProgram
    {
    	public function __construct()
    	{
    		for($i=0;$i<10;$i++)
    		{
    			$memory = round((memory_get_usage(true) / 1048576),5)." Mo";
    			$this->createTree();
    			echo $memory."<br>";	
    		}
    	}
     
    	/**
    	 * Théoriquement, la mémoire devrait se vider à la sortie de cette fonction,
    	 * mais ce n'est pas le cas !
    	 */
    	public function createTree()
    	{
    		$tree = new Tree();
     
    		//correction 1/3
    		$tree->__destruct();	
    	}
     
     
    }
     
    class Tree 
    {
    	public $tree;
    	public function __construct()
    	{
    		$root = new Node();
    		$this->tree = $root;
    		for($i=0;$i<10;$i++)
    		{
    			$node = new Node();
    			for($cpt=0;$cpt<1000;$cpt++)
    			{
    				$node2 = new Node();	
    				$node2->parent = $node;
    				$node->children[] = $node;
    			}
     
    			$node->parent = $root;
    			$root->children[] = $node;
    		}				
    	}
     
    	//correction 2/3
    	public function __destruct()
    	{
    		if($this->tree != NULL)
    		{ 
    			foreach($this->tree->children as $child)
    			{
    				$child->__destruct();
    			}
    		}
    	}
    }
     
    class Node
    {
    	public $parent;
    	public $children = array();
    	public $value;
     
    	public function __construct()
    	{
    		$this->value = "------------------------------------------------------------------";	
    	}
     
    	//correction 3/3
    	public function __destruct()
    	{
    		$this->children = array();
    	}
    }
    Résultat :
    0.25 Mo
    0.75 Mo
    0.75 Mo
    0.75 Mo
    0.75 Mo
    0.75 Mo
    0.75 Mo
    0.75 Mo
    0.75 Mo
    0.75 Mo
    en résumé, j'ai ajouté des appels explicites au destructeur pour chaque node.

    Cela dit, je n'ai pas trouvé d'informations pour gérer efficacement les arborescences en PHP.
    Si vous connaissez de "bonnes pratiques" pour ce genre de cas, je suis preneur

  4. #4
    Expert confirmé
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 342
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 342
    Billets dans le blog
    17
    Par défaut
    PHP gère très mal la mémoire dès qu'on utilise des objets. Exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <?php
        class Foo
        {
            public $data ;
     
            public function __construct( )
            {
                $this->data = range(0, 10000) ;
            }
     
            public function __destruct( )
            {
                echo "Je suis bien détruit !\r\n" ;
            }
        }
     
        header('Content-Type: text/plain') ;
     
        echo memory_get_usage(TRUE), "\r\n" ;
        $o = new Foo( ) ;
        echo memory_get_usage(TRUE), "\r\n" ;
        unset($o) ;
        echo memory_get_usage(TRUE), "\r\n" ;
    ?>
    Donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    262144
    1048576
    Je suis bien détruit !
    524288
    Seule solution : attendre PHP5.3 et son garbage collector.


    EDIT : oups, grilled, j'aurai pas dû aller me faire un sandwich pdt la rédaction du msg

Discussions similaires

  1. fuite de mémoire ?
    Par salseropom dans le forum C
    Réponses: 2
    Dernier message: 12/01/2006, 16h19
  2. Réponses: 1
    Dernier message: 02/12/2005, 14h18
  3. fuite de mémoire
    Par mamag dans le forum MFC
    Réponses: 17
    Dernier message: 19/08/2005, 10h42
  4. Fuite de mémoire en utilisant le template list
    Par schtroumpf_farceur dans le forum Langage
    Réponses: 9
    Dernier message: 18/07/2005, 20h44
  5. Réponses: 8
    Dernier message: 17/10/2002, 12h52

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo