M2 icon indicating copy to clipboard operation
M2 copied to clipboard

Memory leak in creating a sequence

Open mahrud opened this issue 3 years ago • 5 comments

I believe the following line has a memory leak:

f = () -> (scan(0..10^7, i -> ());)

At least it seems like after several times running f(), M2 grinds to a halt.

I should say, even running:

a = (1..10^7);
clearAll()
collectGarbage()

several times seems to do the same, so maybe this is something else? (I'm assuming clearAll and collectGarbage do something, right?)

cc: @jkyang92

mahrud avatar Aug 15 '22 16:08 mahrud

The problem is that even in a line with a semicolon at the end, the value of the expression is saved. Compare:

i13 : 4;

i14 : o13

o14 = 4

i15 : (4;)

i16 : o15

o16 = o15

o16 : Symbol

DanGrayson avatar Aug 18 '22 11:08 DanGrayson

The value of the output is one object. How can it possibly require gigabytes of memory? That doesn't explain the scan example either, where the value that goes in the first parameter of scan isn't saved in any accessible dictionaries.

mahrud avatar Aug 18 '22 14:08 mahrud

Yes, but you said you ran it several times. And every top level expression has an integer stored with it, to indicate what sort of thing it actually is. And an element of ZZ is represented by a pointer to an object returned by mpir or gmp, which contains a length field, too. And there is overhead in libgc -- it has to keep track of the locations and lengths of all allocated objects, for later freeing. Suppose that adds up to 100 bytes -- then 10^7 of those is a gigabyte.

DanGrayson avatar Aug 18 '22 14:08 DanGrayson

@mahrud Is this kind of what you did?

i1 : f = () -> scan(0..10^7, i -> ())

o1 = f

o1 : FunctionClosure

i2 : elapsedTime f()
 -- 1.12672 seconds elapsed

i3 : for i from 1 to 100 do f()

This doesn't seem to leak to me (uses consistently 1.37 GB). That said, maybe it would be nice if 1..10^7 would not expand before the loop?

mikestillman avatar Aug 18 '22 14:08 mikestillman

By several times I meant like 3 times!

i1 : run "free -h"
               total        used        free      shared  buff/cache   available
Mem:            15Gi       6.4Gi       1.4Gi       1.4Gi       7.7Gi       7.3Gi
Swap:           23Gi       1.6Gi        22Gi

o1 = 0

i2 : f = () -> (scan(0..10^7, i -> ()););

i3 : f();

i4 : f();

i5 : f();

i6 : run "free -h"
               total        used        free      shared  buff/cache   available
Mem:            15Gi       8.5Gi       224Mi       1.4Gi       6.8Gi       5.2Gi
Swap:           23Gi       1.6Gi        22Gi

o6 = 0

mahrud avatar Aug 18 '22 14:08 mahrud