# High memory usage when substituting variables

I need to make a lot of variable substitutions in multivariate polynomials. However, I only need to store one polynomial at a time and I only need to make one substitution at a time. Nonetheless sage uses a lot of memory. This memory is not freed until sage is killed.

Here is a small example:

var("x y z")

# A polynomial in three variables (The Trott quartic):
poly=12^2*(x^4+y^4)-15^2*(x^2+y^2)*z^2+350*x^2*y^2+9^2*z^4
poly=poly.polynomial(ZZ)

pnt=[1,2,3]

# Makes a certain variable subsitution, defined by pt, n times.
def test_subs(f,pt,n):
for i in xrange(n):
temp=f.substitute(x=x+pt*z,y=y+pt*z,z=pt*z)
#temp=f(x=x+pt*z,y=y+pt*z,z=pt*z) #This also uses a lot of memory.


When i run test_subs(poly,pnt,100000) I can see the memory usage ticking up from around 1% up to nearly 2%. if I then run the function again the ticking starts at 2%, and so on. In the real problem I have my program eventually fills up all memory and then crashes.

Can you see why this is happening and do you know how to prevent it from happening?

edit retag close merge delete

I confirm the steady increase. This is not reduced by gc.collect(). Maybe it is a Singular issue (Singular is used by Sage in case of multivariate polynomials).

Maybe http://trac.sagemath.org/ticket/17494 is related. In any case the output of get_memory_usage() increases too.

This is almost certainly a Singular problem. The example is not leaving an undue number python objects around. Furthermore, the symbolic ring can be taken out completely and the problem persists. If you declare:

R.<x,y,z>=ZZ[]


you can declare the polynomial immediately, and x,y,z will be actual polynomials. This suggests that sage/singular is currently leaking even on basic polynomial arithmetic . I find it hard to believe that this would go unnoticed in Singular proper, so I expect that this leak has a different origin from the one in #17494.

Still there in sage 9.3.rc4

sage: R.<x,y,z> = QQ[]
sage: import gc
sage: _ = gc.collect(); get_memory_usage()
9160.3125
sage: for _ in range(100000): _ = (x*y + x^2 + 2*z).subs(x=x+y, y=y+2*x, z=x-y)
sage: _ = gc.collect(); get_memory_usage()
9170.3125
sage: for _ in range(100000): _ = (x*y + x^2 + 2*z).subs(x=x+y, y=y+2*x, z=x-y)
sage: _ = gc.collect(); get_memory_usage()
9182.3125


Looks like #27261