What's more, if you create a sub that creates a big string, and the sub uses that string as the return value, then two copies of that string will live in memory EVEN THOUGH you created it with vec() function. Once you're outside the sub, you can only access one copy, and once you undef it outside the sub, it deletes only one copy! This is really weird behavior. I don't understand it at all. But again, I have played around... and I have noticed that if I pass the variable as an argument, then I only one copy of the variable exists in memory:
#!/usr/bin/perl -w use strict; use warnings; sub myfunc_1 { my $A = ''; vec($A, 20000000, 8) = 0; return $A; } sub myfunc_2 { vec($_[0], 100000000, 8) = 0; return 0; } $b = <STDIN>; my $BIGSTRING = ''; myfunc_2($BIGSTRING); # memory usage is normal. $b = <STDIN>; undef $BIGSTRING; # Pff! Gone from memory! TINYPERL.EXE memory # usage visibly shrinks in Windows Task Manager. $b = <STDIN>; my $STRING2 = myfunc_1(); # memory usage is double! $b = <STDIN>; undef $STRING2; # Deletes one copy only $b = <STDIN>;

CONCLUSION: If you write a sub that reads something, let's say, you write a sub called ReadFile() you don't want to return the contents of the file as the return value of the sub, because then two copies of the data will exist in memory. You pass the buffer as an argument to the sub, and then the sub fills it up using

 $_[1] = 'CONTENT';

Perhaps this is why sysread() also works the same way; instead of returning the bytes that were read from the file, it expects the buffer to be passed to it as an argument. The first argument is the file handle, the second is the buffer and the third is the number of bytes to read. And it returns the number of bytes that were read instead of the actual bytes!

ALSO NOTE: Even if your sub does not spell out "return $BIGSTRING;" it still returns the multi-megabyte string if that was the return value of the last statement in the sub. And even if you do not use the return value of the sub, it still gets stuck in memory!!!

#!/usr/bin/perl -w use strict; use warnings; sub MemoryEaterFunc { my $A = ''; vec($A, 20000000, 8) = 0; # Create a large string $A .= $_[0]; # Add to it. Do something. # Evaluate the last statement, # and that is the return value of the sub! even if # you don't write return $A; it still returns it. # If you want the function to not return the big string, # then put 'return 0;' at the end of the sub. } $a = <STDIN>; MemoryEaterFunc(2); # Eats memory and doesn't release it $a = <STDIN>;

You say, "All right fine! I will return zero and then see what happens!"

Unfortunately, the MemoryEaterFunc() will still gobble up 20 megabytes of RAM even if it returns zero, and you do not use its return value. To actually make sure that it doesn't gobble up memory, we need to undef the variable $A before exiting the sub!

Interestingly, if you do not undef $A and you use that same sub repeatedly, it doesn't gobble up an additional 20 MB EACH time. It only uses 20 MB total. Period. (In a way, this proves that Perl uses heap memory instead of stack.)

MemoryEaterFunc(2);
MemoryEaterFunc(2);
MemoryEaterFunc(2);
MemoryEaterFunc(2);
# At this point, memory usage is 20 MB.
$b = <STDIN>;

Okay, so let's fix this thing so it doesn't waste memory anymore:

sub MemoryEaterFunc_FIXED { my $A = ''; vec($A, 20000000, 8) = 0; # Create a large string $A .= $_[0]; # Add to it. Do something. undef $A; }

Now the memory eater doesn't eat memory anymore. It uses 20 MB of memory INSIDE the sub, but then once it gets done, it no longer holds onto that memory.


In reply to Re: Memory usage double expected by harangzsolt33
in thread Memory usage double expected by sectokia

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



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.