Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Re: scalar reference and length

by rjt (Curate)
on Oct 29, 2019 at 18:53 UTC ( #11108098=note: print w/replies, xml ) Need Help??


in reply to scalar reference and length

Edit: When I posted this, the question asked if the following code would make a copy of the string:

my $x = \" VERY VERY BIG STRING ....."; my $len = length( $$x );

Everything below the <hr> answers that question. The question has since been edited with much more information, which made my initial answer no longer make (much) sense.

my $s = shift; will not, by itself, increase memory usage, at least on recent Perls:

my $string = 'Long string' x 100000; sub psau() { print grep { /\b$$\b/ } `ps au` } # POSIX platforms sub bar { psau } sub foo { my $s = shift; psau } sub mod { my $s = shift; $s =~ s/Long/LONG/g; psau } psau; bar($string); foo($string); mod($string); psau;

On my system, that shows an increase only on the last call which modifies the string, mod($string).

This copy-on-write behavior was introduced in Perl 5.20, so results would differ on older Perls, and some specifics will be platform dependent.


There is no size penalty, aside from the insignificant size of the reference itself:

use Devel::Size qw< size total_size >; sub size_print($\$) { my ($name, $ref) = @_; printf "%20s %5d %5d\n", $name, size($ref), total_size($ref); } my $string = 'Long string' x 100; printf "%20s %5s %s\n", qw<Name size total_size>; size_print '$string', $string; my $collection = [ ]; size_print '$collection (empty)', $collection; push @$collection, \$string; size_print '$collection ( one )', $collection; push @$collection, \$string; size_print '$collection ( two )', $collection; __END__ Name size total_size $string 1134 1134 $collection (empty) 24 88 $collection ( one ) 24 1278 $collection ( two ) 24 1302

As to whether there is a performance penalty to dereferencing the string, the answer to that is unfortunately yes:

use Benchmark qw<cmpthese>; my $string = 'Long string' x 1000; my $really_long = $string x 100; my $ref = \$string; my $long_ref = \$really_long; cmpthese(-5, { map { $_ => "length($_)" } qw< $string $$ref $really_long $$long_r +ef > }); __END__ Rate $$long_ref $$ref $really_long $s +tring $$long_ref 17305170/s -- -9% -36% + -38% $$ref 18937129/s 9% -- -30% + -32% $really_long 27185304/s 57% 44% -- + -2% $string 27870647/s 61% 47% 3% + --

I included two drastically different strings to illustrate the point that Perl does not need to scan the entire string to know the length of the scalar, since the length is part of the internal representation. The performance penalty is for the dereference only.

use strict; use warnings; omitted for brevity.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://11108098]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (6)
As of 2020-04-08 16:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    The most amusing oxymoron is:
















    Results (45 votes). Check out past polls.

    Notices?