#715: Parents probably not reclaimed due to too much caching
-------------------------------------------------------------------+--------
       Reporter:  robertwb                                         |         
Owner:  somebody                     
           Type:  defect                                           |        
Status:  needs_work                   
       Priority:  major                                            |     
Milestone:  sage-pending                 
      Component:  coercion                                         |    
Resolution:                               
       Keywords:  weak cache coercion Cernay2012                   |   Work 
issues:                               
Report Upstream:  N/A                                              |     
Reviewers:  Jean-Pierre Flori, Simon King
        Authors:  Simon King, Jean-Pierre Flori                    |     Merged 
in:                               
   Dependencies:  #9138, #11900, #11599, to be merged with #11521  |      
Stopgaps:                               
-------------------------------------------------------------------+--------

Comment (by SimonKing):

 Too bad. I tried to add the following to the old patch:
 {{{
 #!diff
 diff --git a/sage/structure/coerce_dict.pxd
 b/sage/structure/coerce_dict.pxd
 --- a/sage/structure/coerce_dict.pxd
 +++ b/sage/structure/coerce_dict.pxd
 @@ -1,6 +1,7 @@
  cdef class TripleDict:
      cdef Py_ssize_t _size
      cdef buckets
 +    cdef dict _refcache
      cdef double threshold
      cdef TripleDictEraser eraser
      cdef get(self, object k1, object k2, object k3)
 diff --git a/sage/structure/coerce_dict.pyx
 b/sage/structure/coerce_dict.pyx
 --- a/sage/structure/coerce_dict.pyx
 +++ b/sage/structure/coerce_dict.pyx
 @@ -18,8 +18,6 @@
  # removing dead references from the cache
  ############################################

 -cdef dict _refcache = {}
 -
  cdef class TripleDictEraser:
      """
      Erases items from a :class:`TripleDict` when a weak reference becomes
 @@ -108,8 +106,10 @@
                  del bucket[i:i+4]
                  self.D._size -= 1
                  break
 -        cdef list L = _refcache[k1,k2,k3]
 -        del L[L.index(r)]
 +        try:
 +            self.D._refcache.__delitem__((k1,k2,k3))
 +        except KeyError:
 +            pass

  cdef class TripleDict:
      """
 @@ -432,22 +432,24 @@
          PyList_Append(bucket, h3)
          PyList_Append(bucket, value)
          try:
 -            PyList_Append(_refcache.setdefault((h1 , h2, h3), []),
 -                KeyedRef(k1,self.eraser,(h1, h2, h3)))
 +            ref1 = KeyedRef(k1,self.eraser,(h1, h2, h3)))
          except TypeError:
 -            PyList_Append(_refcache.setdefault((h1, h2, h3), []), k1)
 +            ref1 = k1
          if k2 is not k1:
              try:
 -                PyList_Append(_refcache.setdefault((h1 , h2, h3), []),
 -                    KeyedRef(k2,self.eraser,(h1, h2, h3)))
 +                ref2 = KeyedRef(k2,self.eraser,(h1, h2, h3)))
              except TypeError:
 -                PyList_Append(_refcache.setdefault((h1, h2, h3), []), k2)
 -        if k3 is not k1 and k3 is not k2:
 +                ref2 = k2
 +        else:
 +            ref2 = None
 +        if k3 is not k2 or k3 is not k1:
              try:
 -                PyList_Append(_refcache.setdefault((h1 , h2, h3), []),
 -                    KeyedRef(k3,self.eraser,(h1, h2, h3)))
 +                ref3 = KeyedRef(k3,self.eraser,(h1, h2, h3)))
              except TypeError:
 -                PyList_Append(_refcache.setdefault((h1, h2, h3), []),k3)
 +                ref3 = k3
 +        else:
 +            ref3 = None
 +        self._refcache[h1,h2,h3] = (ref1,ref2,ref3)
          self._size += 1

      def __delitem__(self, k):
 }}}

 However, with the resulting code, the memory leak discussed here
 reappears!

 So far, I can only speculate why that has happened. It could be that
 moving _refcache into the `TripleDict` created a reference cycle (namely,
 `TripleDict` will occur as attribute to parents, and the parents occur as
 references in _refcache). If a `__del__` method is involved, the items in
 the reference cycle can't be collected.

 If this holds true, then one has to have the necessary references in an
 ''external'' dictionary. But perhaps one can still ensure that the data
 associated with one `TripleDict` will be removed, as soon as the
 `TripleDict` gets garbage collected.

-- 
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/715#comment:200>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, 
and MATLAB

-- 
You received this message because you are subscribed to the Google Groups 
"sage-trac" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sage-trac?hl=en.

Reply via email to