#12616: The LP are not deallocated because of cyclic references !
----------------------------------+-----------------------------------------
   Reporter:  ncohen              |          Owner:  ncohen       
       Type:  defect              |         Status:  needs_review 
   Priority:  major               |      Milestone:  sage-5.0     
  Component:  linear programming  |       Keywords:               
Work_issues:                      |       Upstream:  N/A          
   Reviewer:                      |         Author:  Nathann Cohen
     Merged:                      |   Dependencies:               
----------------------------------+-----------------------------------------

Comment(by SimonKing):

 Hi Nathann,

 Replying to [comment:12 ncohen]:
 > > In the ticket description, you mention a few reports on memory leaks.
 Is the objective of this ticket to fix all of them?

 I think I stand corrected in what I said about Python's garbage collector.

 If I am not mistaken, the garbage collector is involved ''only'' if there
 are reference cycles. Hence, if an object deleted and is not contained in
 a reference cycle, it will be immediately removed, even if garbage
 collection is switched off:
 {{{
 sage: class C:
 ....:     def __del__(self):
 ....:         print "deleting the object"
 ....:
 sage: class D:
 ....:     pass
 ....:
 sage: c = C()
 sage: import gc
 sage: gc.disable()
 sage: del c
 deleting the object
 }}}

 Hence, since your patch destroys one reference cycle, it makes sure that a
 deleted mixed integer linear program will be immediately removed.

 Here is an example in which garbage collection comes in. The slight
 problem is that if one has a `__del__` method in the cycle, then the
 garbage collector does not know what to do. Hence, in my example, I am
 creating a cycle of instances of D, with a pointer to an instance of C,
 such that one sees when things are deleted:
 {{{
 sage: d1 = D()
 sage: d2 = D()
 sage: d1.d = d2
 sage: d2.d = d1
 sage: c = C()
 sage: d1.c = c
 sage: del d1
 sage: del c
 sage: del d2
 }}}
 Nothing happens! The `__del__` method of c is not called!! Hence, with
 garbage collection disabled, the reference cycle `d1 <--> d2` can not be
 removed.

 Let's do the collection manually:
 {{{
 sage: gc.collect()
 deleting the object
 681
 }}}
 Aha! The reference cycle, and thus the last reference to c, has gone.

 The last example shows that we must not have `__del__` in the reference
 cycle:
 {{{
 sage: d = D()
 sage: c = C()
 sage: d.c = c
 sage: c.d = d
 sage: del c
 sage: del d
 sage: gc.collect()
 4
 sage: len([x for x in gc.get_objects() if isinstance(x,C)])
 1
 }}}
 So, c is not deleted and will not be deleted! That would be a memory leak.

 What does that mean for your patch?

  - I still believe it is a good idea to avoid reference cycles, when
 possible. However, I don't think that your patch fixes an actual leak.
  - By now, I think that your example ''does'' demonstrate the fix, and
 that it works stably.

 So, let me run doctests, and if they pass, I give it a positive review.

-- 
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/12616#comment:13>
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