Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

scalar reference and length

by coyocanid (Sexton)
on Oct 29, 2019 at 22:20 UTC ( [id://11108095]=perlquestion: print w/replies, xml ) Need Help??

coyocanid has asked for the wisdom of the Perl Monks concerning the following question:

If I have a scalar ref holding on to a big string, and take its length, will dereferencing it into length cause the string to be copied? I'm hoping since length is a builtin, it would not.
my $x = \" VERY VERY BIG STRING ....."; my $len = length( $$x );
If it were a sub, however, it would be
sub foo { my $s = shift; my $r = \$s; print "FOO ($r)\n" } my $X = "SOMESTRING"; my $O = \$X; my $R = \$X; print "NOTFOO ($R,$O)\n"; + foo( $$R );
outputs
NOTFOO (SCALAR(0x9393f8),SCALAR(0x9393f8)) FOO (SCALAR(0x9394a0))
EDIT, after some help from my friends One delightful thing I learned is that the @_ elements are _not_ copies. A sub does not have to copy.
sub foo { my $r = \$_[0]; print "FOO ($r)\n" } my $X = "SOMESTRING"; my $O = \$X; my $R = \$X; print "NOTFOO ($R,$O)\n"; + foo( $$R );
outputs
NOTFOO (SCALAR(0x1ac23e8),SCALAR(0x1ac23e8)) FOO (SCALAR(0x1ac23e8))

Original content restored below by GrandFather for reference.

If I have a scalar ref holding on to a big string, and take its length, will dereferencing it into length cause the string to be copied?

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

Replies are listed 'Best First'.
Re: scalar reference and length
by choroba (Cardinal) on Oct 29, 2019 at 22:51 UTC
    It's the
    my $s = shift;
    that copies the string. If you just use $_[0] in the sub, no copying happens. Moreover, recent perl versions have the "copy on write", which means the copy isn't created until it's needed because it becomes different to the original.

    Try running your script with kind of a memory monitoring tool. I just used "Resource monitoring" in my LXDE Panel. Clearly, using shift with some modification of the string consumed twice as more memory.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: scalar reference and length
by rjt (Curate) on Oct 29, 2019 at 22:53 UTC

    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.


    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
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11108095]
Approved by Paladin
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (3)
As of 2024-04-25 21:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found