Je sais que sérialiser un objet est (à ma connaissance) le seul moyen de copier efficacement un objet (aussi longtemps que ce n'est pas d'état indiquant que Par exemple, car j'utilise des rails, je pourrais toujours utiliser edit strong>: Notez que sa mise en œuvre est quelque chose que j'ai déjà couvert - je ne veux pas remplacer les méthodes de copie peu profondes existantes (telles que io code> et ce que rien), mais est une bien particulièrement efficace qu'une autre? p>
ActiveSupport :: json code>,
to_xml code> - et de ce que je peux dire que je peux dire que je peux dire que l'objet est l'un des les moyens les plus acceptés de le faire. Je m'attendrais à ce que le marshalling soit probablement le plus efficace de ceux-ci puisqu'il s'agit d'un rubis interne, mais je manque quelque chose? P>
DUP code> et
clone < / Code>), donc je finirai simplement à ajouter probablement
objet :: profond_copy code>, résultat de celui des méthodes ci-dessus (ou des suggestions que vous avez :) qui a le moins de frais généraux. p>
3 Réponses :
Je pense que vous devez ajouter une méthode initialisée_copy à la classe que vous copiez. Ensuite, mettez la logique pour la copie profonde de là. Ensuite, lorsque vous appelez Clone, il tirera cette méthode. Je ne l'ai pas fait, mais c'est ma compréhension.
Je pense que le plan b serait juste remplacer la méthode du clone: p> sortie p> Je suis sûr que vous pourriez faire ce refroidisseur avec un petit bricolage mais pour le meilleur ou pour le pire qui est probablement comment je le ferais. p> p>
Apprécier les commentaires - c'est un moyen de le remplacer, mais il finit par être mis en œuvre serait idéalement discrètement et laissez les méthodes d'origine à la copie peu profonde intacte (par exemple, j'ajouterais simplement objet :: profond_copy code> ). Avez-vous vu quoi que ce soit à propos de la méthode offrant le moins de frais généraux?
Mis à jour. J'espère que ça aide un peu.
+1, Voir un exemple ici: blog.rubybestpractices.com/posts/ rklemme / ...
Je me demandais la même chose, j'ai donc comparé quelques techniques différentes les unes contre les autres. J'étais principalement préoccupé par les matrices et les hachages - je n'ai pas testé d'objets complexes. Peut-être sans surprise, une mise en œuvre personnalisée sur clone s'est révélée être la plus rapide. Si vous recherchez une mise en œuvre rapide et facile, le maréchal semble être le moyen d'aller.
J'ai également comparé une solution XML avec des rails 3.0.7, non indiqué ci-dessous. C'était beaucoup, beaucoup plus lent, ~ 10 secondes pour seulement 1000 itérations (les solutions ci-dessous toutes les 10 000 fois pour la référence). P>
Deux notes concernant ma solution JSON. Tout d'abord, j'ai utilisé la variante C, version 1.4.3. Deuxièmement, cela ne fonctionne pas réellement à 100%, car les symboles seront convertis en cordes. P>
C'était tout géré avec Ruby 1.9.2P180. P>
user system total real 0.230000 0.000000 0.230000 ( 0.239257) (Marshal) 3.240000 0.030000 3.270000 ( 3.262255) (YAML) 0.590000 0.010000 0.600000 ( 0.601693) (JSON) 0.060000 0.000000 0.060000 ( 0.067661) (Custom) 0.090000 0.010000 0.100000 ( 0.097705) (MessagePack)
Hey @évan Pon, j'ai ajouté MessagePack dans vos exemples. C'est une bonne option.
MessagePack semble vraiment rapide (2 fois plus rapide que sur mesure sur ma machine). Pourriez-vous mettre à jour la réponse avec la recommandation de l'utiliser au lieu du maréchal?
@Andreybotalov, MessagePack ne gère que quelques classes - essentiellement des chiffres, des cordes, des tableaux et des hachages. Si vous avez d'autres types d'objets, tels qu'un objet de date, cela ne fonctionnera pas pour vous.
J'ai trouvé que si les valeurs que vous êtes en profondeur de clonage sont plus grandes (plus de clés, plus imbriquées, de plus grandes valeurs), le code de rubis personnalisé est plus lent que la messagerie.
Probablement la raison pour laquelle Ruby ne contient pas de clonage profond avec la complexité du problème. Voir les notes à la fin.
Pour faire un clone qui "copier en profondeur", des hachages, des tableaux et des valeurs élémentaires, c'est-à-dire une copie de chaque élément dans l'original telle que la copie aura les mêmes valeurs, Mais de nouveaux objets, vous pouvez utiliser ceci: p> Si vous souhaitez redéfinir le comportement de la méthode code> clone de Ruby's code>, vous pouvez le nommer juste Par exemple:. P> Clone Code> au lieu de
DeepcLone Code> (dans 3 places), mais je ne sais pas que la redéfinition de la redéfinition du comportement du clone de Ruby affectera les bibliothèques rubis, ou rubis sur des rails, donc cavalier. Personnellement, je ne peux pas recommander le faire p>
a = {'a'=>M.new(nil,'g'),'b'=>'y'} => {"a"=>#<M:0x00000001f8bf78 @z="g">, "b"=>"y"}
b = a.deepclone => {"a"=>#<M:0x00000001766f28 @z="g">, "b"=>"y"}
puts "#{a['a'].object_id} / #{b['a'].object_id}" => 12303600 / 12269460
puts "#{a['b'].object_id} / #{b['b'].object_id}" => 16811400 / 17802280