Vitja Makarov, 05.07.2011 09:17:
2011/7/5 Stefan Behnel:
Vitja Makarov, 05.07.2011 08:21:
I was thinking about implementing new super() with no arguments.
http://trac.cython.org/cython_trac/ticket/696

The problem is where to store __class__, I see two options here:

1. Add func_class member to CyFunction, this way __class__ will be
private and not visible for inner functions:
2. Put it into closure

The second option has the advantage of requiring the field only when super()
is used, whereas the first impacts all functions.

I would expect that programs commonly have a lot more functions than
specifically methods that use a no-argument call to super(), so this may
make a difference.


So, now classes are created the following way:

class_dict = {}
class_dict.foo = foo_func
class = CreateClass(class_dict)

So after class is created I should check its dict for CyFunction
members (maybe only ones that actually require __class__)
and set __class__:

for value in class.__dict__.itervalues():
    if isinstance(value, CyFunction) and value.func_class is WantClass:
        value.func_class = class

Remember that no-args super() can only be used in functions that are literally written inside of a class body, so we actually know at compile time which functions need this field. We can thus do better than a generic loop over all fields. We even have the function object pointers directly available in the module init function where we create the class body.

BTW, we also need a way to make this work for cdef classes. No idea how different that would be.


OTOH, not all methods have a closure, so creating one just to store the
"__class__" field is very wasteful, in terms of both runtime and memory
overhead. A lot more wasteful than paying 8 bytes of memory for each
function, with no additional time overhead.

Going this way it only requires to initialize closure:

Yes, and that's costly.


Btw, first way requires cyfunction signature change, it would accept
cyfunction object as first argument.

We currently pass the binding (i.e. owning) object, right?


This also could help to solve default args problem.

And potentially other problems, too. Think of heap allocated modules, for example.

http://trac.cython.org/cython_trac/ticket/173
http://trac.cython.org/cython_trac/ticket/218

Seeing this, I'm all for using a field in CyFunction.


And I don't think that __class__ should be use somewhere outside super()

Agreed. CPython simply uses a compile time heuristic ("is there a function
call to something global named 'super'?") when creating this field, so it's
strictly reserved for this use case.

BTW, I like the irony in the fact that CPython essentially gives Cython
semantics to the "super" builtin here, by (partially) evaluating it at
compile time.

Yeah, I think Cython super with no args should be a little bit faster
then classic one.

I think speed isn't really all that important here. Calling Python methods is costly enough anyway.

IMO, the main reason for the heuristic is to prevent class objects from being kept alive by their methods, except for the single case where super() is used. Keeping a class alive just because one of its methods is still used somewhere can be very costly, depending on the content of the class dict. It also creates a reference cycle, which is another costly thing in CPython as it requires a GC run over the whole class dict to get cleaned up.

The situation for modules is at least slightly different, as modules do not tend to get unloaded, so there's always a reference to them from sys.modules. If that ever gets removed, it's really ok if it takes time to clean things up.

Stefan
_______________________________________________
cython-devel mailing list
cython-devel@python.org
http://mail.python.org/mailman/listinfo/cython-devel

Reply via email to