#15432: Use a callback with a weak reference to WeakValueDictionary
-------------------------------------+-------------------------------------
       Reporter:  nbruin             |        Owner:
           Type:  enhancement        |       Status:  needs_review
       Priority:  major              |    Milestone:  sage-6.0
      Component:  memleak            |   Resolution:
       Keywords:                     |    Merged in:
        Authors:                     |    Reviewers:
Report Upstream:  N/A                |  Work issues:
         Branch:                     |       Commit:
  u/nbruin/ticket/15432              |  9bb9241572468d4bc0563f06fe6fffcc8b12c345
   Dependencies:                     |     Stopgaps:
-------------------------------------+-------------------------------------

Comment (by nbruin):

 Replying to [comment:3 SimonKing]:
 > Just to make sure: Is there a dependency for this ticket? It seems that
 we need #13394 (which is merged). But #15367 is orthogonal, isn't it?

 The branch here descends directly from master, which recently had
 5.13beta3 merged. Therefore, as posted, this ticket has no dependencies.
 Since it only touches one file, that isn't even present in the branch for
 #15367 (its branch split off before 5.13beta3 merger), I expect no merge
 problems with that ticket.

 I actually have a bit of trouble coming up with an example that shows a
 difference in behaviour for !WeakValueDictionary (before this ticket it's
 not weakly refererrable, making examples particularly tricky). With the
 following code:
 {{{
 %cpaste
 import gc
 from sage.misc.weak_dict import WeakValueDictionary
 from sage.structure.coerce_dict import MonoDict
 def Nobj(t):
     return len([1 for o in gc.get_objects() if isinstance(o,t)])
 def TestTcollect(T,args=()):
     N=Nobj(T)
     print "Number of T-objects before we start:",N
     L=[T(*args) for i in range(100)]
     M=MonoDict(11)
     for i in range(len(L)-1):
         M[L[i]]=L[i+1]
     Nnew=Nobj(T)
     print "Number of T-objects after list construction:",Nnew
     print "Throwing away references:"
     del L
     Nnew=Nobj(T)
     if Nnew == N:
         print "no GC required to get rid of objects";
     j=0
     while Nnew>N:
         j+=1
         _=gc.collect()
         Ntemp=Nobj(T)
         if Ntemp >= Nnew:
             raise RuntimeError("we're not collecting at all!")
         Nnew=Ntemp
     print "number of collects required:",j
 class dd(dict):
     "a weakly reffable and easily recognized dict class"
     pass
 class selfref(object):
     def __init__(self):
         self.D=self
 --
 }}}
 I'm getting with a self-referencing class:
 {{{
 sage: TestTcollect(selfref)
 Number of T-objects before we start: 0
 Number of T-objects after list construction: 100
 Throwing away references:
 number of collects required: 100
 }}}
 The test doesn't work for dict itself (they have their own freelist etc.
 so
 the object count you get back can't be trusted), but we can do it on a
 subclass:
 {{{
 sage: TestTcollect(dd)
 Number of T-objects before we start: 0
 Number of T-objects after list construction: 100
 Throwing away references:
 no GC required to get rid of objects
 number of collects required: 0
 }}}
 For this patched `WeakValueDictionary` we're still getting problematic
 behaviour:
 {{{
 sage: TestTcollect(sage.misc.weak_dict.WeakValueDictionary)
 Number of T-objects before we start: 29
 Number of T-objects after list construction: 129
 Throwing away references:
 number of collects required: 100
 }}}
 Whereas python's own is clean:
 {{{
 sage: TestTcollect(weakref.WeakValueDictionary)
 Number of T-objects before we start: 3
 Number of T-objects after list construction: 103
 Throwing away references:
 no GC required to get rid of objects
 number of collects required: 0
 }}}
 As is (at least our old) `TripleDict`:
 {{{
 sage: TestTcollect(sage.structure.coerce_dict.TripleDict,(11,))
 Number of T-objects before we start: 180
 Number of T-objects after list construction: 280
 Throwing away references:
 no GC required to get rid of objects
 number of collects required: 0
 }}}
 So my guess is that we've overlooked another self reference in
 !WeakValueDictionary.

 Note that our previous `sage.misc.weak_dict.WeakValueDictionary` wasn't
 weakly
 referrable so this test doesn't apply in that case.

--
Ticket URL: <http://trac.sagemath.org/ticket/15432#comment:4>
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 unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sage-trac.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to