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).
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.
$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.