Plain old coercions are cached on the codomain. Since our generic,
global objects like ZZ and QQ tend to coerce universally *into* other
rings, this tends to mean that the morphisms, which hold strong
references to domain and codomain, are hanging off the more temporary
objects, i.e., ZZ and QQ are not holding references TO them. That's
good because it gives a chance to recycle rings that aren't in use
anymore.

However, for binary op discovery, the two operands are often
essentially symmetric, so there is no preferred one to store info on.
In fact, it seems the coercion framework ships this off into some
global table elsewhere. Great care is taken to not hold strong
references in the keys of the dictionaries, but the coercion morphisms
themselves are held with strong references (that's the point!).
However, those morphisms themselves hold strong references to domain
and codomain!

Example:

sage: import gc
sage: T=type(GF(2))
sage: gc.collect()
0
sage: len(list(o for o in gc.get_objects() if type(o) is T))
1
sage:
sage: for p in prime_range(2,300):
....:     k=GF(p)
....:     _=ZZ(1)+k(1)
....:
sage: del k, _
sage: gc.collect()
0
sage: len(list(o for o in gc.get_objects() if type(o) is T))
62

We see that after garbage collection the finite fields still remain in
memory, even though the user does not hold any reference to them.

To illustrate that the coercion model indeed has references to these:

sage: cm = sage.structure.element.get_coercion_model()
sage: maps, actions = cm.get_cache()
sage: L = maps.values() #as far as I can tell, these are strong refs
sage: V=[l[0].codomain() for l in L if l is not None and l[0] is not
None]
sage: len(list(v for v in  V  if type(v) is T))
62

I don't see how we can avoid this. In principle the coercion maps
don't need to hold references to their domain and codomain, because
these are part of the key by which they are looked up. So in principle
one could have a kind of "coercion map stub" stored that gets
reequiped with domain and codomain upon lookup in the relevant
dictionary. However, doing something like that might be hard to do
without significant speed penalty. Plus forbidding people to refer to
domain and codomain in a map is a rather severe restriction (think
morphism CRT morphism  Z/3Z x Z/5Z -> Z/15Z for instance)

A heuristic/hacky way to do it is by storing the morphism on one of
the concerned rings (chosen by a heuristic to likely be the most short-
lived one) and change the global dictionary to be weakly keyed and
only hold a redirection "look on first" or "look on second" to tell
the system where to look for the actual morphism.

Comments? (Especially Robert Bradshaw's insights would be very
valuable here).

-- 
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 http://groups.google.com/group/sage-devel?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to