#14058: Weakly reference binary operation codomains
-----------------------------------+----------------------------------------
       Reporter:  robertwb         |         Owner:  rlm         
           Type:  enhancement      |        Status:  needs_review
       Priority:  major            |     Milestone:  sage-5.7    
      Component:  memleak          |    Resolution:              
       Keywords:                   |   Work issues:              
Report Upstream:  N/A              |     Reviewers:              
        Authors:  Robert Bradshaw  |     Merged in:              
   Dependencies:                   |      Stopgaps:              
-----------------------------------+----------------------------------------

Comment (by nbruin):

 Sadly, the performance hit is quite noticeable.
 {{{
 a=ZZ(1)
 b=QQ(1)
 c=ZZ['x'](1)
 d=b+c

 def test(x,y):
   for i in xrange(10^6):
     _=x+y
 }}}
 Within a run, timing `test` seems fairly consistent. However, between
 different compiles of the same code I'm observing fluctuations of up to
 `0.10s` in timings. Lucky/unlucky memory layout?
 Anyway, with patch:
 {{{
 sage: %time test(a,b)
 CPU times: user 2.15 s, sys: 0.00 s, total: 2.15 s
 Wall time: 2.16 s
 sage: %time test(a,c)
 CPU times: user 2.25 s, sys: 0.00 s, total: 2.25 s
 Wall time: 2.26 s
 sage: %time test(b,c)
 CPU times: user 16.83 s, sys: 0.00 s, total: 16.83 s
 }}}
 without patch
 {{{
 sage: %time test(a,b)
 CPU times: user 1.54 s, sys: 0.00 s, total: 1.54 s
 Wall time: 1.55 s
 sage: %time test(a,c)
 CPU times: user 1.64 s, sys: 0.00 s, total: 1.64 s
 Wall time: 1.64 s
 CPU times: user 15.68 s, sys: 0.00 s, total: 15.68 s
 Wall time: 15.76 s
 }}}
 For `test(a,a)`, `test(b,b)`, `test(c,c)` there doesn't seem to be a
 difference (luckily!)

 The penalties seem to be about `0.6s`, `0.6s`, `1.2s`, which is rather
 consistent with 1,1,2 extra lookups.

 This indicates to me it may be worth trying storing a weakref to the
 morphism instead, since that can probably be dereferenced faster than a
 coercion lookup on the codomain. Logically this should be equivalent.
 We're just storing a weakref to the object we're interested in rather than
 instructions where to go and lookup the object we want.

 Caveat:

 For stored coercions of the type
 `(R,S, ...): (None,<map S->R>)`
 or
 `(R,S, ...): (<map R->S>,None)`
 the codomain is part of the key, so deletion of the codomain (which is a
 prerequisite for the morphism being deleted and hence the weakref dying)
 implies removal of the weak key entry in `TripleDict`.

 However, for stored coercions of the type
 `(R,S,...): (<map R->C>,<map S->C>)`
 we could have that `C` and the weakrefs to the morphisms die, but that
 would not trigger the removal from the `TripleDict`. So we could still
 encounter dead weakrefs (but much less than one would perhaps initially
 think!) It's not really much different from how [attachment:14058-weak-
 binop.patch] handles dead weakrefs.

 Major problem for immediately applying this idea:
 {{{
 sage: M=QQ.coerce_map_from(ZZ)
 sage: import weakref
 sage: weakref.ref(M)
 TypeError: cannot create weak reference to 'sage.rings.rational.Z_to_Q'
 object
 }}}

-- 
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/14058#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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to