Hi Jeroen,

Am Montag, 3. Dezember 2018 11:46:50 UTC+1 schrieb Jeroen Demeyer:
>
> I am studying the coercion model in detail, looking for optimization 
> opportunities. One source of slow-down is the use of weak references. 
>
> Over time, more and more places in Sage use weak references. But I'd 
> like to look at the big picture and see where weak references should be 
> used and where not. 
>
> Take coercion maps for example. The coercion model stores a weak 
> reference to the coercion maps and the maps also store a weak reference 
> to the domain (but not the codomain). 
>
> It's not clear to me why this double weak reference is needed, but maybe 
> I'm missing something. It seems more logical to use strong references in 
> the coercion map but then store a weak reference to the map. 
>

I was involved in the development of the weakly cached coercion system, but 
I am afraid I don't recall all the rationales behind the construction. 
Let's try to explain anyway...

First, I summarise how currently coercion data is stored:

   1. Each parent has a cache of coercion maps for which the parent is 
   codomain. The cache uses a hash table (MonoDict) with a weak reference to 
   the domain (the key) and a strong reference to the coercion map.
   2. In some cases, coercion between two parents P,Q involves the creation 
   of a new parent R, such that both P and Q coerce into R. That's a 
   complicated construction, therefore the result is cached. This cache 
   currently is a global hash table (TripleDict), with keys being P and Q that 
   are weakly referenced. There is a weak reference to both coercion maps (P 
   to R and Q to R).
   3. A similar scheme is used for actions. Here, in addition, the operator 
   (operator.mul, operator.add etc) is used as key.

How does that prevent memory leaks? Let there be a coercion map f from Q to 
P, and maps gP from P to R and gQ from Q to R. Let C be the global cache. 
By => resp. -> I mean a strong resp. weak reference.

   - We have 
   - C->gP, C->gQ, C->Q, C->P
      - P=>f, P->Q
      - f=>Q, f->P, fP=>R, fQ=>R, fP->P, fQ->Q
      - R=>fP, R=>fQ, R->P, R->Q
   - There thus is a reference cycle involving a coercion map and its 
   codomain. All other references in the above graph are weak.
      - If there is no external strong reference chain from a global object 
      to P, then the pair (fP,fQ) is removed from C, and P together with f will 
      be collected.
      - If there is no external strong reference chain from a global object 
      to Q, then the pair (fP,fQ) is removed from C and f is removed from P's 
      cache of incoming coercion maps.
      - Mild problem: If there is an external strong reference to, say, f, 
      then it is possible that Q becomes garbage collected anyway, and we would 
      end up with an invalid map.
   
I was just drawing the above graph on a napkin, and if I see that 
correctly, changing ANY weak reference of the above graph into a *strong* 
reference would create a situation where an external strong reference chain 
from a global object to one parent would extend *internally* (i.e., inside 
of the coercion system) to *another* parent (or it would introduce a strong 
reference chain from the global object C to some parent) --- and that's a 
memory leak.

So, Jeroen, I guess changing some weak references into strong references 
won't work. But I'd be happy to stand corrected.

Best regards,
Simon

-- 
You received this message because you are subscribed to the Google Groups 
"sage-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sage-devel+unsubscr...@googlegroups.com.
To post to this group, send email to sage-devel@googlegroups.com.
Visit this group at https://groups.google.com/group/sage-devel.
For more options, visit https://groups.google.com/d/optout.

Reply via email to