I have an app which reads a giant chunk of textual data into a scalar, sometimes even GBs in size. I use substr on that scalar to read most of the data into another scalar and replace the extracted data with an empty string, because it is not needed in the first scalar anymore. What I've found recently was that Perl is not freeing the memory of the first scalar, while it is recognizing that its logical length has changed. So what I need to do is extract the data from the first scalar into a third again, undef the first scalar und put the extracted data back in place. Only this way the memory occupied by the first scalar is really freed up. Assigning undef to that scalar or some other value less than the allocated block of memory doesn't change anything about the allocated memory.
The following is what I do now:
$$extFileBufferRef = substr($$contentRef, $offset, $length, '');
$length = length($$contentRef);
my $content = substr($$contentRef, 0, $length);
$$contentRef = undef( $$contentRef) || $content;
$$contentRef might be e.g. 5 GBs in size in the first line, I extract 4,9 GB of data and replace the extracted data. The second line would now report e.g. 100 MBs of data as the length of the string, but e.g. Devel::Size::total_size would still output that 5 GB of data are allocated for that scalar. And assigning undef or such to $$contentRef doesn't seem to change a thing about that, I need to call undef as a function on that scalar.
I would have expected that the memory behind $$contentRef is already at least partially freed after substr was applied. Doesn't seem to be the case...
So, is memory only freed if variables go out of scope? And if so, why is assigning undef different to calling undef as a function on the same scalar?