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.