Mail Archives: cygwin/2007/01/23/15:40:47
Corinna Vinschen wrote:
> On Jan 22 11:26, Yitzchak Scott-Thoennes wrote:
>> Corinna wrote:
> $a = "a" x (100 * 1024 * 1024);
> sleep 5;
>> > "a" --> malloc (2 bytes)
>> > x 100 Megs --> realloc (100 Megs) + malloc (100 Megs)
>> >
>> > So the result is that each string of 100 Megs requires 200 Megs of
>> > memory. Doing this once is no problem, but doing it over and over
>> > again will hit the maximum memory available twice as early.
>>
>> This is as I would expect. Most operators have a target, a temporary
>> lexical, allocated to store their results. Like all lexicals, these
>> hold on to any memory they have allocated in the hope of saving having
>> to allocate it a second time.
>
> The problem is that it's *not* reused. If you use strace when running
> this script you see the allocations as I described them. When the
> 2 Gigs virtual memory size for the process are used up, mmap (which
> is called by malloc for big memory chunks) is called and returns -1,
> MAP_FAILED. Then malloc tries to get the memory from the heap, when
> that fails, it just prints "Out of memory!", munmaps half of the above
> allocations and then exits.
Right, *each* x operation has it's own target. If you undef $a, $b, etc.
at the end and wrap the whole thing in a for (1..2) loop, you'll see the
second time round that space is only allocated once per statement.
Or just have one x operation, and only see the "leaked" memory allocated
once:
#!/usr/bin/perl
for ($a, $b, $c, $d, $e, $f, $g, $h, $h, $i, $j, $k, $l) {
$_ = "a" x (100 * 1024 * 1024);
sleep 5;
}
sleep 95;
x= doesn't behave the same way. It doesn't use the target, since it knows
where the result should go, so the following doesn't have the problem you
observed:
#!/usr/bin/perl
$a = "a"; $a x= (100 * 1024 * 1024);
sleep 5;
$b = "b"; $b x= (100 * 1024 * 1024);
sleep 5;
$c = "c"; $c x= (100 * 1024 * 1024);
sleep 5;
$d = "d"; $d x= (100 * 1024 * 1024);
sleep 5;
$e = "e"; $e x= (100 * 1024 * 1024);
sleep 5;
$f = "f"; $f x= (100 * 1024 * 1024);
sleep 5;
$g = "g"; $g x= (100 * 1024 * 1024);
sleep 5;
$h = "h"; $h x= (100 * 1024 * 1024);
sleep 5;
$h = "h"; $h x= (100 * 1024 * 1024);
sleep 5;
$i = "i"; $i x= (100 * 1024 * 1024);
sleep 5;
$j = "j"; $j x= (100 * 1024 * 1024);
sleep 5;
$k = "k"; $k x= (100 * 1024 * 1024);
sleep 5;
$l = "l"; $l x= (100 * 1024 * 1024);
sleep 100;
It is possible to free the memory used by targets, but only by putting the
code in an anonymous closure:
#!/usr/bin/perl
my $dummy;
&{sub {
$dummy if 0;
$a = "a" x (1 * 1024 * 1024);
sleep 5;
$b = "b" x (1 * 1024 * 1024);
sleep 5;
$c = "c" x (1 * 1024 * 1024);
sleep 5;
$d = "d" x (1 * 1024 * 1024);
sleep 5;
$e = "e" x (1 * 1024 * 1024);
sleep 5;
$f = "f" x (1 * 1024 * 1024);
sleep 5;
$g = "g" x (1 * 1024 * 1024);
sleep 5;
$h = "h" x (1 * 1024 * 1024);
sleep 5;
$h = "h" x (1 * 1024 * 1024);
sleep 5;
$i = "i" x (1 * 1024 * 1024);
sleep 5;
$j = "j" x (1 * 1024 * 1024);
sleep 5;
$k = "k" x (1 * 1024 * 1024);
sleep 5;
$l = "l" x (1 * 1024 * 1024);
sleep 5;
}};
sleep 95;
$dummy forces the anonymous sub to be a closure, which gets it's own pad
(storage space for lexicals and targets) each time the sub{} is encountered
at runtime. Without it, the sub{} holds on to it's pad even after the
code reference it returns is freed.
There has been some work towards implementing a "use less 'memory';" pragma
that may make perl less greedy, but there's no timetable for that or clear
plan for what it would do.
--
I'm looking for a job: http://perlmonks.org/?node=ysth#looking
--
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Problem reports: http://cygwin.com/problems.html
Documentation: http://cygwin.com/docs.html
FAQ: http://cygwin.com/faq/
- Raw text -