Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

My thanks to iguanodon for the reference and install trace for Clone and Jeffa for the quickstart on its use. Special thanks to Merlyn for the reference to his article which told me what to look for in testing, and to everyone else for their help.

As you can see from the Benchmark below, not all deepcopy methods are equal in terms of performance. (Data::Dumper isn't tested because I couldn't work out how to use it for this. See comments in code below).

C:\test>228543 Benchmark: running CloneCopy, DeepCopy, StorableCopy , each for at least 1 CPU seconds ... CloneCopy: 1 wallclock secs ( 1.10 usr + 0.01 sys = 1.11 CPU) @ +27625.00/s (n=30719) DeepCopy: 1 wallclock secs ( 1.10 usr + 0.00 sys = 1.10 CPU) @ +20539.93/s (n=22635) StorableCopy: 1 wallclock secs ( 1.03 usr + 0.00 sys = 1.03 CPU) @ +541.67/s (n=559) Rate StorableCopy DeepCopy CloneCopy StorableCopy 542/s -- -97% -98% DeepCopy 20540/s 3692% -- -26% CloneCopy 27625/s 5000% 34% -- Difference found!

As you can see, Clone wins hands down, with my own (modified from the original) attempt coming a deceptively creditable second.

What I mean by deceptively, is that despite it's relatively tardy performance, Storable really takes second place honours because, as is indicated by the "Differences found!" output at the bottom, not all the routines do the same thing. As was pointed out above by ihb, my DeepCopy routine does handle recursive structures. The difference is clearly shown in the side-by-side Dumper output below. A second flaw is that it doesn't handle bless'd references at all. I haven't tested the others for this as it isn't a requirement for my purposes.

Data::Dumper comparison of cloned structures

$DeepCopy = { $CloneCopy = { $Stor +ableCopy = { 'rrs1' => [ 'rrs1' => [ 'rr +s1' => [ \\1, \\1, + \\1, \\2, \\2, + \\2, \\3, \\3, + \\3, \\4, \\4, + \\4, \\5 \\5 + \\5 ], ], +], 'rrs2' => [ 'rrs2' => [ 'rr +s2' => [ $VAR1->{'rrs1'}[0], $VAR2->{'rrs1'}[0], + $VAR3->{'rrs1'}[0], $VAR1->{'rrs1'}[1], $VAR2->{'rrs1'}[1], + $VAR3->{'rrs1'}[1], $VAR1->{'rrs1'}[2], $VAR2->{'rrs1'}[2], + $VAR3->{'rrs1'}[2], $VAR1->{'rrs1'}[3], $VAR2->{'rrs1'}[3], + $VAR3->{'rrs1'}[3], $VAR1->{'rrs1'}[4] $VAR2->{'rrs1'}[4] + $VAR3->{'rrs1'}[4] ], ], ] +, 'h1' => { 'h1' => { 'h1 +' => { 'A' => 1, 'A' => 1, + 'A' => 1, 'B' => 2, 'B' => 2, + 'B' => 2, 'C' => 3, 'C' => 3, + 'C' => 3, 'D' => 4, 'D' => 4, + 'D' => 4, 'E' => 5 'E' => 5 + 'E' => 5 }, }, } +, 'rs' => [ 'rs' => [ 'rs +' => [ ${$VAR1->{'rrs1'}[0]}, ${$VAR2->{'rrs1'}[0]}, + ${$VAR3->{'rrs1'}[0]}, ${$VAR1->{'rrs1'}[1]}, ${$VAR2->{'rrs1'}[1]}, + ${$VAR3->{'rrs1'}[1]}, ${$VAR1->{'rrs1'}[2]}, ${$VAR2->{'rrs1'}[2]}, + ${$VAR3->{'rrs1'}[2]}, ${$VAR1->{'rrs1'}[3]}, ${$VAR2->{'rrs1'}[3]}, + ${$VAR3->{'rrs1'}[3]}, ${$VAR1->{'rrs1'}[4]} ${$VAR2->{'rrs1'}[4]} + ${$VAR3->{'rrs1'}[4]} ], ], ] +, 'self' => [ 'self' => $VAR2->{'rs'} 'se +lf' => $VAR3->{'rs'} ${$VAR1->{'rrs1'}[0]} };, }; ${$VAR1->{'rrs1'}[1]}, ${$VAR1->{'rrs1'}[2]}, ${$VAR1->{'rrs1'}[3]}, ${$VAR1->{'rrs1'}[4]} ] };

The benchmark code

#! perl -slw use strict; use Clone qw[clone]; use Data::Dumper; use Storable qw[dclone freeze]; use Benchmark qw[cmpthese]; sub deepcopy{ return $_[0] unless ref $_[0]; return [ map{ deepcopy($_) } @{$_[0]} ] if ref $_[0] eq 'ARRAY +'; return { map{ deepcopy($_) } %{$_[0]} } if ref $_[0] eq 'HASH' +; return \do{ ${$_[0]} }; } sub factorial { my ($f,$n) = (1,shift); $f *= $n-- while( $n ); $f; } sub multicheck { my $check = factorial($#_); my ($i, @ok) = (0, (0) x @_); while (@_) { my $first = shift; for my $next (@_) { $ok[$i] += ($first eq $next); } $i++; } my $count = do{ local $a; $a += $_ for @ok; $a; }; return $count == $check; } my @rs = \do{1..5}; my @rrs1 = \(@rs); my @rrs2 = \(@rs); my %h1 = do{ my $key='A'; map{ $key++ => $_} 1..5; }; my %hash = ( rs=> \@rs, rrs1=> \@rrs1, rrs2=> \@rrs2, h1=>\%h1 ); $hash{self} = $hash{rs}; my $DeepCopy = deepcopy( \%hash ); my $CloneCopy = clone( \%hash ); my $StorableCopy= dclone( \%hash ); #print Dumper [\%hash, $CloneCopy, $StorableCopy, $DeepCopy]; =pod Comment (moan) The following code should, according to my reading of the Data::Dumper + pod, result in $DDumperCopy becoming a ref to a copy of %hash,, but it doesn't? :( my $DDumperCopy; $Data::Dumper::Purity = 1; $DDumperCopy = eval( Dumper(\%hash) ) and warn $@ if $@; print Dumper $DDumperCopy; =cut cmpthese( -1, { DeepCopy => '$DeepCopy = deepcopy( \%hash );', CloneCopy => '$CloneCopy = clone( \$hash );', StorableCopy=> '$StorableCopy = dclone( \%hash );', # DDumperCopy => '', }); my $strDeepCopy = freeze( $DeepCopy ); my $strCloneCopy = freeze( $CloneCopy ); my $strStorableCopy = freeze( $StorableCopy ); print "\nDifferences found!" unless multicheck( $strDeepCopy, $strCloneCopy, $strStorableCo +py ); #print Dumper $DeepCopy, $CloneCopy, $StorableCopy # unless multicheck( $strDeepCopy, $strCloneCopy, $strStorableCo +py );

BTW: If anyone has a (reference to a) better version of my multicheck() routine, preferably one that will tell me which of the things passed differed if only one does, I'd love to see it.


Examine what is said, not who speaks.

The 7th Rule of perl club is -- pearl clubs are easily damaged. Use a diamond club instead.


In reply to Re: Deepcopy of complex structures. (resolved) by BrowserUk
in thread Deepcopy of complex structures. by BrowserUk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (2)
As of 2024-04-24 13:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found