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! #### $DeepCopy = { $CloneCopy = { $StorableCopy = { 'rrs1' => [ 'rrs1' => [ 'rrs1' => [ \\1, \\1, \\1, \\2, \\2, \\2, \\3, \\3, \\3, \\4, \\4, \\4, \\5 \\5 \\5 ], ], ], 'rrs2' => [ 'rrs2' => [ 'rrs2' => [ $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'} 'self' => $VAR3->{'rs'} ${$VAR1->{'rrs1'}[0]} };, }; ${$VAR1->{'rrs1'}[1]}, ${$VAR1->{'rrs1'}[2]}, ${$VAR1->{'rrs1'}[3]}, ${$VAR1->{'rrs1'}[4]} ] }; #### #! 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, $strStorableCopy ); #print Dumper $DeepCopy, $CloneCopy, $StorableCopy # unless multicheck( $strDeepCopy, $strCloneCopy, $strStorableCopy );