Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
27261: move tests in an independent file
Browse files Browse the repository at this point in the history
  • Loading branch information
videlec committed May 28, 2021
1 parent ddc9a6b commit edf8847
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 100 deletions.
60 changes: 0 additions & 60 deletions src/sage/libs/singular/polynomial.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -156,66 +156,6 @@ cdef int singular_polynomial_call(poly **ret, poly *p, ring *r, list args, poly
sage: (3*x*z)(x,x,x)
3*x^2
TESTS:
Test that there is no memory leak in evaluating polynomials (see
:trac:`27261`). Note that (lib)Singular has pre-allocated buckets, so we
have to run a lot of iterations to fill those up first::
sage: import resource
sage: import gc
sage: def leak_ZZ(N):
....: R.<x, y> = ZZ[]
....: p = (x + y)^10
....: gc.collect()
....: before = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
....: for i in range(N):
....: _ = p(x, y)
....: _ = p(x + y, y)
....: _ = p(1, -1)
....: _ = p(0, 0)
....: gc.collect()
....: after = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
....: return (after - before) * 1024 # ru_maxrss is in kilobytes
sage: def leak_GF49(N):
....: F.<a> = GF(7^2)
....: R.<x,y> = F[]
....: p = (x + 2*y - 1)^10
....: gc.collect()
....: before = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
....: for i in range(N):
....: _ = p(a, a)
....: _ = p(x, y)
....: _ = p(x + y, y)
....: _ = p(a + x, a)
....: gc.collect()
....: after = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
....: return (after - before) * 1024 # ru_maxrss is in kilobytes
Loop (at most 30 times) until we have 6 consecutive zeros when
calling ``leak(10000)``. Depending on the operating system, it is
possible to have several non-zero leak values in the beginning, but
after a while we should get only zeros. The fact that we require 6
zeros also means that Singular's pre-allocated buckets should not
be sufficient if there really would be a memory leak. ::
sage: zeros = 0
sage: for i in range(30): # long time
....: nGF49 = leak_GF49(1000)
....: nZZ = leak_ZZ(1000)
....: print("Leaked {} and {} bytes".format(nGF49, nZZ))
....: if nGF49 == nZZ == 0:
....: zeros += 1
....: if zeros >= 6:
....: print("done")
....: break
....: else:
....: zeros = 0
Leaked ...
...
Leaked 0 and 0 bytes
done
"""
cdef long l = len(args)
cdef ideal *to_id = idInit(l,1)
Expand Down
40 changes: 0 additions & 40 deletions src/sage/rings/polynomial/multi_polynomial_libsingular.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -125,46 +125,6 @@ Check if :trac:`6160` is fixed::
sage: b-j*c
b - 1728*c
Test memory leak from :trac:`27261`::
sage: import resource
sage: import gc
sage: def leak_subs(N):
....: R = PolynomialRing(ZZ, 'x', 50)
....: d1 = {str(g): g for g in R.gens()}
....: d2 = {str(g): R.zero() for g in R.gens()}
....: d3 = {str(g): ZZ.one() for g in R.gens()}
....: p1 = sum(R.gens())
....: p2 = R.zero()
....: gc.collect()
....: before = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
....: for i in range(N):
....: _ = p1.subs(**d1)
....: _ = p2.subs(**d1)
....: _ = p1.subs(**d2)
....: _ = p2.subs(**d2)
....: _ = p1.subs(**d3)
....: _ = p2.subs(**d3)
....: gc.collect()
....: after = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
....: return (after - before) * 1024 # ru_maxrss is in kilobytes
sage: zeros = 0
sage: for i in range(40):
....: n = leak_subs(20)
....: print("Leaked {} bytes".format(n))
....: if n == 0:
....: zeros += 1
....: if zeros >= 10:
....: print("done")
....: break
....: else:
....: zeros = 0
Leaked ...
...
Leaked 0 bytes
done
.. TODO::
Implement Real, Complex coefficient rings via libSINGULAR
Expand Down
90 changes: 90 additions & 0 deletions src/sage/tests/polynomial_leaks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
r"""
This file gather leaks that appeared in :trac:`27261`.
"""
import resource
import gc

from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing

def get_resources():
gc.collect()
return resource.getrusage(resource.RUSAGE_SELF).ru_maxrss

def test_leak(f, args, repeat, n_success):
r"""
Test that there is no memory when calling ``f(*args)``.
Note that (lib)Singular has pre-allocated buckets, so we have to run a lot
of iterations to fill those up first.
"""
zeros = 0
for i in range(repeat):
n = f(*args)
if n == 0:
zeros += 1
if zeros >= n_success:
return
else:
zeros = 0
raise RuntimeError('leak f={} args={} repeat={} n_success={}'.format(f, args, repeat, n_success))

def leak_call(base, nvars, repeat):
r"""
TESTS::
sage: from sage.tests.polynomial_leaks import test_leak, leak_call
sage: for base in [ZZ, QQ, GF(7), GF(49), AA, ZZ['y']]:
....: test_leak(leak_call, (base, 2, 10), 40, 10)
....: test_leak(leak_call, (base, 50, 10), 40, 10)
"""
assert nvars >= 2
R = PolynomialRing(base, 'x', nvars)
gens = R.gens()
p1 = R.zero()
p2 = R.one()
p3 = sum(gens)
p4 = (gens[0] + gens[1])**10
polys = [p1, p2, p3, p4]
v1 = list(gens)
v2 = [v1[0] + v1[1]] + v1[1:]
v3 = [base.zero()] * nvars
v4 = [(-1)**i * base.one() for i in range(nvars)]
v5 = [base.gen() + gens[0]] + gens[1:]
values = [v1, v2, v3, v4, v5]
before = get_resources()
for i in range(repeat):
for p in polys:
for v in values:
_ = p(*v)
_ = p(v)
after = get_resources()
return after - before

def leak_subs(base, nvars, repeat):
r"""
TESTS::
sage: from sage.tests.polynomial_leaks import test_leak, leak_subs
sage: for base in [ZZ, QQ, GF(7), GF(49), AA, ZZ['y']]:
....: test_leak(leak_subs, (base, 2, 10), 50, 10)
....: test_leak(leak_subs, (base, 50, 10), 50, 10)
"""
R = PolynomialRing(base, 'x', nvars)
gens = R.gens()
p1 = R.zero()
p2 = R.one()
p3 = sum(gens)
p4 = (gens[0] + gens[1])**10
polys = [p1, p2, p3, p4]
d1 = {str(g): g for g in R.gens()}
d2 = {str(g): R.zero() for g in R.gens()}
d3 = {str(g): base.one() for g in R.gens()}
values = [d1, d2, d3]
before = get_resources()
for i in range(repeat):
for p in polys:
for d in values:
_ = p.subs(**d)
_ = p.subs(d)
after = get_resources()
return after - before

0 comments on commit edf8847

Please sign in to comment.