If you have some kind of real-time, graphical memory resource display on your system, you can see the processes discussed above in action and play with them. (I'm using the memory "Performance" display of Windows 7 Task Manager, running Strawberry Perl 5.14.4.1.)
This example subroutine creates a lexical (my) array and increases its size to a fairly large value. (You may have to adjust the sizes of the following examples according to the memory resources of your system.) It then abandons the array and returns. The memory of the array, no longer referenced, is garbage collected. The for-loop calls the subroutine over and over, and you can see a small, constant blip in memory usage while the loop is running. (Be patient; the loop takes significant time to create and destroy all that stuff.) When the loop (and the program) finishes execution, system memory usage returns to its pre-loop, pre-program baseline value.
c:\@Work\Perl\monks>perl -wMstrict -le
"sub Sa {
my @ra;
$#ra = 100_000_000;
return;
}
;;
for (0 .. 100) {
Sa();
}
"
(Update: The Sa() subroutine was changed to add an explicit return statement to make it absolutely clear that the routine returns nada and the lexical @ra array inside it is no longer referenced.)
This example is almost the same, except that the subroutine returns a reference to the array created within it. The reference is assigned to a lexical scalar variable created within the scope of the for-loop, and the variable goes out of existence almost immediately because the end of the loop (and its scope) is reached. My system shows some difference in memory usage as compared to the Sa() subroutine example: peak usage is the same, but during the execution of the loop, there is some irregular variation between the peak value and the pre-execution, baseline memory usage value. I attribute this variation to the fact that unreferenced memory objects are only marked for garbage collection when their reference count goes to zero; the actual act of recovering the memory is determined by multiple factors and is not, IIRC, necessarily deterministic.
c:\@Work\Perl\monks>perl -wMstrict -le
"sub Sb {
my @ra;
$#ra = 100_000_000;
return \@ra;
}
for (0 .. 100) {
my $arrayref = Sb();
}
"
(This example also takes a noticable time to run.)
The third example differs in that the reference returned by the subroutine is saved in the for-loop in an array outside the scope of the loop instead of being immediately thrown away. In this case, the memory allocated within the subroutine during its execution cannot be garbage-collected because it is still being referenced! A graphical display of memory should show a steadily increasing usage while the loop is running. Usage will be constant during the sleep period after the loop terminates. During this time, all references to memory allocated in the Sc() subroutine are still in existence in the @save_references array. Then all the references in the array are destroyed, and their referents are garbage-collected. A return to baseline memory usage is seen that continues to program termination (when memory usage continues at baseline).
c:\@Work\Perl\monks>perl -wMstrict -le
"sub Sc {
my @ra;
$#ra = 10_000_000;
return \@ra;
}
;;
my @save_references;
for my $i (0 .. 20) {
$save_references[$i] = Sc();
}
sleep 8;
;;
@save_references = ();
sleep 8;
"
Give a man a fish: <%-{-{-{-<
|