Clonage vs. Copiage.

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Clonage vs. Copiage.

par Sékiltoyai » 22 juil. 2007, 02:18

Si tu regardes mon code Sekil tu verras que justement il illustre le fait que serialize() ne les garde pas. Ce qui est logique au fond puisque serialize() transforme quelque chose d'abstrait en une chaîne de caractère, il serait par conséquent illogique de garder les références sur des données volatiles comme les variables qui disparaissent en fin de script.
Je viens de vérifier, en effet, serialize se comporte tout à fait normalement, c'est bizarre que j'ai cru entendre le contraire... Enfin bon, c'est vrai que le comportement contraire aurait été plus que louche, c'est mieux comme cela :).

par Hywan » 19 juil. 2007, 16:39

En fait, je dois boucler une collection d'objets. Mais c'est bon, j'ai trouvé une meilleure façon de procéder. J'instancie mes objets en dehors de ma boucle, et je me fais un tas de setters pour tout remettre. Y a moyen sans que ce soit trop lourd.

Comme ça, pas de clonage, pas de copie, et 1 seule instance. Mais je vais tout de même utiliser le clonage sur 1 objet en particulier.

Merci à vous deux : pour les tests, et pour les informations :) Sujet clos (peut être l'épingler ? ça pourrait servir pour d'autres, je sais pas).

par Genova » 19 juil. 2007, 16:18

J'ai oublié des mots :mrgreen:

En gros je voulais dire que ce serait pas très logique d'un point de vu conceptuel d'utiliser un clone pour créer des objets. Mais si ton projets doit manipuler des tas d'objets issus de la même classe, apparemment clone semble plus rapide.

par Hywan » 19 juil. 2007, 16:12

- ce ne serait pas spécialement du point de vu du fonctionnement du langage et du lecteur du code
Pas compris ça ...

Je travaille sur un outil où j'ai pas mal d'objets, avec une conception assez lourde. Et le moindre gain de ressource n'est pas à négliger. Merci pour les tests en tout cas :)

par Genova » 19 juil. 2007, 15:31

Si tu regardes mon code Sekil tu verras que justement il illustre le fait que serialize() ne les garde pas. Ce qui est logique au fond puisque serialize() transforme quelque chose d'abstrait en une chaîne de caractère, il serait par conséquent illogique de garder les références sur des données volatiles comme les variables qui disparaissent en fin de script.

Alors la différence entre new et clone en terme de performance, j'ai fait un benchmark :

(100000 itérations)

Code : Tout sélectionner

class A { public $titi = array('toto', 'tutu', 'tyty'); private $test = 'salut'; } $a = new A; // 0.18666601181 $b = clone $a; // 0.0804181098938

Code : Tout sélectionner

class A { public $titi = array('toto', 'tutu', 'tyty'); private $test = 'salut'; public function __clone() { } } $a = new A; // 0.182492017746 $b = clone $a; // 0.171550989151

Code : Tout sélectionner

class A { public $titi = array('toto', 'tutu', 'tyty'); private $test = 'salut'; public function __construct() { } public function __destruct() { } } $a = new A; // 0.308668851852 $b = clone $a; // 0.144464969635

Code : Tout sélectionner

class A { public $titi = array('toto', 'tutu', 'tyty'); private $test = 'salut'; public function __construct() { } public function __destruct() { } public function __clone() { } } $a = new A; // 0.314460992813 $b = clone $a; // 0.230401039124

J'ai aussi essayé en mettant un tableau de 100000 éléments dans la propriété $titi, ça ne change rien.

En conclusion cloner semble plus rapide qu'instancier, mais à mon avis c'est une mauvaise idée car :
- l'optimisation est très faible (insignifiante, a moins de manipuler une collection de 100000 objets dans ta page ...)
- ce ne serait pas spécialement du point de vu du fonctionnement du langage et du lecteur du code

par Hywan » 19 juil. 2007, 14:26

Faites le test, vous serez fixé :)

par Sékiltoyai » 19 juil. 2007, 14:20

Avec le serialize() / unserialize(), les références ne sont pas conservées.
T'en es sur ? J'ai lu ici que seriralize() gérait les références...

par Hywan » 19 juil. 2007, 14:18

D'accord, mais théoriquement ? Si quelqu'un aurait une idée, ce serait bien :)

par Genova » 19 juil. 2007, 14:14

Voilà la principale différence entre les deux :
class A
{
	public $toto;
}
$var = 'bonjour';

$a = new A;
$a->toto = &$var;

$b = clone $a;
$b->toto = 'salut';

echo $var . '<br />';

$c = unserialize(serialize($a));

$c->toto = 'lol';

echo $var;
Avec un clonage basique, l'objet sera cloné, mais si les propriétés ont une référence sur quelque chose, cette référence sera gardée.
Avec le serialize() / unserialize(), les références ne sont pas conservées.

Ensuite en terme de ressource, à mon avis ça doit dépendre des cas, essaie de faire des benchmark en temps et en mémoire pour tester ;)

par Hywan » 19 juil. 2007, 14:07

LoL. J'ai compris le clonage. T'as pas compris ma question, mais c'est sûrement de ma faute.

On a deux façons d'obtenir un clone apparement :
$a = new A;
$b = unserialize(serialize($a));
ou
$a = new A;
$b = clone $a;
Ou est la différence ?

Et j'aimerais savoir si instancier un objet est plus ou moins lourd que de le cloner. Qu'est-ce qui est le plus coûteux en ressources ?
$a = new A;
$b = new A;
et
$a = new A;
$b = clone $a;
En considérant qu'avec la méthode __clone() on réinitialise l'objet.

Merci.

par Sékiltoyai » 19 juil. 2007, 14:07

Le problème, c'est que, à l'instar de son homologue en java, clone fait une copie superficielle, c'est à dire si certaines attributs de l'objet à cloner sont des tableaux ou des objets, la copie se fera par référence. Pour faire un clonage récursif, il faut le faire soi même (Le plus simple, c'est en implémentant la méthode magique __clone(), le plus infaillible, en parcourant toutes les classes ou les tableaux dans sa fonction de clonage faite maison)...

par Genova » 19 juil. 2007, 13:58

Salut,
un code valant mieux qu'un long discours, avec ça tu devrais comprendre directement la différence entre clonage et pas clonage :
class Test
{
	public $toto;
}

// On instancie une première fois Test et on set la propriété toto sur bidule
$test1 = new Test;
$test1->toto = 'bidule';

// En PHP5, le code ci dessous fait une copie par référence
$test2 = $test1;
// Donc quand je modifie $test2->toto je modifie en fait $test1->toto aussi
$test2->toto = 'nouveau machin';

// La preuve :
echo 'test1->toto = ' . $test1->toto . '<br />';
echo 'test2->toto = ' . $test2->toto . '<br />';
echo '----------<br />';

// Là maintenant je fais un objet $test3 en clonant $test2
$test3 = clone $test2;

// Si je modifie $test3->toto, ben ni $test1 ni $test2 ne seront modifiés
$test3->toto = 'le truc ultime';

// La preuve :
echo 'test1->toto = ' . $test1->toto . '<br />';
echo 'test2->toto = ' . $test2->toto . '<br />';
echo 'test3->toto = ' . $test3->toto . '<br />';[/code]

ce qui affichera à l'écran
[quote]test1->toto = nouveau machin
test2->toto = nouveau machin
----------
test1->toto = nouveau machin
test2->toto = nouveau machin
test3->toto = le truc ultime

Donc en clair si tu veux créer un nouveau objet à partir du premier, mais que tu veux qu'il soit indépendant du premier, il faut le cloner.

Important : en PHP4, lorsque tu fais $test1 = $test2 l'objet est automatiquement cloné. c'est une des différences entre PHP4 et PHP5, et sur un projet totalement orienté objet ça peut jouer sur la portabilité.

Astuce : voici un moyen de rendre le clone portable en PHP4 / PHP5 :
if (version_compare(phpversion(), '5.0') < 0)
{
    eval('function clone($object){return($object);}');
}

Clonage vs. Copiage.

par Hywan » 19 juil. 2007, 13:52

Bonjour,

j'aborde une notion qui est nouvelle pour moi : le clonage, avec le mot clé clone de PHP (5).
Pour avoir une copie (clone ou copie) d'un objet, soit on utilise clone, ou alors la sérialization.

J'aurais aimé avoir votre avis là-dessus. Quelles sont les différences, les avantages, et les inconvénients ? :)

Merci.