[Prev][Next][Index][Thread][Top, Search][Archived Lists][Original Mail]
Re: BUG REPORT: Script that demonstrates a memory leak in 5.002beta1
On Sat, 09 Dec 1995 21:12:00 GMT, Alan Burlison wrote:
>The following short script leaks like a sieve on 5.002beta1, but not at
>all on 5.001m. I have included some memory statistics, and the output of
>myconfig. Some curious things: The number of items pushed onto the
>anonymous array referenced by $leak is critical - any less than 125 and
>the program size remains constant. If $leak is changed to @leak, the
>problem also disappears. Could someone a) confirm that there is a
>problem and b) if so, shed some light on what is causing it?
Here's a summary of the problem and a workaround.
The new sv_add_arena() functionality is used to reclaim AvARRAYs and
HvARRAYs that have a significantly large size. This memory gets added as a
fresh new sv arena. The problem arises when arrays and hashes grow beyond
these significant sizes inside loops which triggers relocation to a larger
contiguous block of memory and reclamation of the old one. Since the
reclamation code is not cognizant of whether it is sitting inside a loop,
this amounts to unconditional scavenging (but not free()ing) of memory.
The immediate workaround is to either compile both hv.c and av.c with
-DSTRANGE_MALLOC, or apply the following slightly more efficient patch (a
bunch of ifdefs really) that always frees [HA]vARRAYs. Until we figure out
a way to put a cap on the amount of reclaimed (but still unused) space and
make sv_add_arena() be conditional based on that, this is may be the
solution.
Doing this also eliminates all symptoms of the bug reported by Andreas a few
days back.
For reference, here are the two test cases that work fine in 5.001n:
while (1) { $leak = {}; for (1..68) { $leak->{$_} = "z"; } }
while (1) { $leak = []; for (1..125) { push(@$leak, "Z"); } }
- Sarathy.
gsar@engin.umich.edu
P.S: A couple of notes:
* I don't know why Larry did not do a sv_add_arena() in av_undef()
but did so in hv_undef()
* why AvMAX(av) rather than AvMAX(av)+1 in the sv_add_arena() call in
av_extend() ?
------------------------------------8<-----------------------------
*** av.c.dist Wed Nov 15 14:26:17 1995
--- av.c Sat Dec 9 23:03:32 1995
***************
*** 82,90 ****
newmax = tmp - 1;
New(2,ary, newmax+1, SV*);
Copy(AvALLOC(av), ary, AvMAX(av)+1, SV*);
if (AvMAX(av) > 64 && !AvREUSED(av))
! sv_add_arena((char*)AvALLOC(av), AvMAX(av) * sizeof(SV*),0);
else
Safefree(AvALLOC(av));
AvALLOC(av) = ary;
#endif
--- 82,92 ----
newmax = tmp - 1;
New(2,ary, newmax+1, SV*);
Copy(AvALLOC(av), ary, AvMAX(av)+1, SV*);
+ #ifdef 0
if (AvMAX(av) > 64 && !AvREUSED(av))
! sv_add_arena((char*)AvALLOC(av), (AvMAX(av)+1) * sizeof(SV*),0);
else
+ #endif
Safefree(AvALLOC(av));
AvALLOC(av) = ary;
#endif
*** hv.c.dist Wed Nov 15 15:00:05 1995
--- hv.c Sat Dec 9 23:10:03 1995
***************
*** 337,342 ****
--- 337,343 ----
assert(tmp >= newsize);
New(2,a, tmp, HE*);
Copy(xhv->xhv_array, a, oldsize, HE*);
+ #if 0
if (oldsize >= 64 && *(char*)&xhv->xnv_nv == 0) {
sv_add_arena((char*)xhv->xhv_array, oldsize * sizeof(HE*), 0);
sv_add_arena(((char*)a) + newsize * sizeof(HE*),
***************
*** 344,349 ****
--- 345,351 ----
SVf_FAKE);
}
else
+ #endif
Safefree(xhv->xhv_array);
#endif
***************
*** 478,487 ****
--- 480,493 ----
#ifdef STRANGE_MALLOC
Safefree(xhv->xhv_array);
#else
+ #if 0
if (xhv->xhv_max < 127 || *(char*)&xhv->xnv_nv)
Safefree(xhv->xhv_array);
else /* We used last half, so use first half for SV arena too. */
sv_add_arena((char*)xhv->xhv_array, (xhv->xhv_max + 1) * sizeof(HE*),0);
+ #else
+ Safefree(xhv->xhv_array);
+ #endif
#endif
if (HvNAME(hv)) {
Safefree(HvNAME(hv));
References: