Permalink
Browse files

events/properties: optimisation pass on mostly __storage access to do…

… a direct C access instead of Python, by declaring correctly an EventDispatcher.

Benchmark is faster: from 8.555312 to 8.188883.
Tested with touchtracer, showcase, make tests and processcraft.
  • Loading branch information...
1 parent 5341f87 commit 330757217edc32417b22ffc7d0d268a044a04a10 @tito tito committed Sep 29, 2012
Showing with 93 additions and 91 deletions.
  1. +7 −0 kivy/_event.pxd
  2. +19 −16 kivy/_event.pyx
  3. +16 −14 kivy/properties.pxd
  4. +51 −51 kivy/properties.pyx
  5. +0 −10 kivy/uix/widget.py
View
@@ -0,0 +1,7 @@
+
+cdef class EventDispatcher(object):
+ cdef dict __event_stack
+ cdef dict __properties
+ cdef dict __storage
+ cpdef dict properties(self)
+ cdef readonly int uid
View
@@ -19,7 +19,6 @@ from functools import partial
from kivy.weakmethod import WeakMethod
from kivy.properties cimport Property, ObjectProperty
-cdef tuple forbidden_properties = ('touch_down', 'touch_move', 'touch_up')
cdef int widget_uid = 0
cdef dict cache_properties = {}
@@ -29,27 +28,25 @@ cdef class EventDispatcher(object):
See the module docstring for usage.
'''
- cdef dict __event_stack
- cdef dict __properties
-
def __cinit__(self, *largs, **kwargs):
global widget_uid, cache_properties
- cdef dict widget_dict = self.__dict__
cdef dict cp = cache_properties
cdef dict attrs_found
cdef list attrs
cdef Property attr
cdef str k
+
self.__event_stack = {}
+ self.__storage = {}
+
__cls__ = self.__class__
# XXX for the moment, we need to create a uniq id for properties.
# Properties need a identifier to the class instance. hash() and id()
# are longer than using a custom __uid. I hope we can figure out a way
# of doing that without require any python code. :)
widget_uid += 1
- widget_dict['__uid'] = widget_uid
- widget_dict['__storage'] = {}
+ self.uid = widget_uid
if __cls__ not in cp:
attrs_found = cp[__cls__] = {}
@@ -58,7 +55,7 @@ cdef class EventDispatcher(object):
uattr = getattr(__cls__, k)
if not isinstance(uattr, Property):
continue
- if k in forbidden_properties:
+ if k == 'touch_down' or k == 'touch_move' or k == 'touch_up':
raise Exception('The property <%s> have a forbidden name' % k)
attrs_found[k] = uattr
else:
@@ -175,6 +172,7 @@ cdef class EventDispatcher(object):
print 'press on button', obj, 'with date:', value
'''
+ cdef Property prop
for key, value in kwargs.iteritems():
if key[:3] == 'on_':
if key not in self.__event_stack:
@@ -183,13 +181,15 @@ cdef class EventDispatcher(object):
handler = WeakMethod(value)
self.__event_stack[key].append(handler)
else:
- self.__properties[key].bind(self, value)
+ prop = self.__properties[key]
+ prop.bind(self, value)
def unbind(self, **kwargs):
'''Unbind properties from callback functions.
Same usage as :func:`bind`.
'''
+ cdef Property prop
for key, value in kwargs.iteritems():
if key[:3] == 'on_':
if key not in self.__event_stack:
@@ -201,7 +201,8 @@ cdef class EventDispatcher(object):
self.__event_stack[key].remove(handler)
break
else:
- self.__properties[key].unbind(self, value)
+ prop = self.__properties[key]
+ prop.unbind(self, value)
def dispatch(self, str event_type, *largs):
'''Dispatch an event across all the handler added in bind().
@@ -224,11 +225,13 @@ cdef class EventDispatcher(object):
#
# Properties
#
- def __proxy_setter(self, dstinstance, name, instance, value):
- self.__properties[name].__set__(dstinstance, value)
+ def __proxy_setter(self, EventDispatcher dstinstance, name, instance, value):
+ cdef Property prop = self.__properties[name]
+ prop.set(dstinstance, value)
- def __proxy_getter(self, dstinstance, name, instance):
- return self.__properties[name].__get__(dstinstance)
+ def __proxy_getter(self, EventDispatcher dstinstance, name, instance):
+ cdef Property prop = self.__properties[name]
+ return prop.get(dstinstance)
def setter(self, name):
'''Return the setter of a property. Useful if you want to directly bind
@@ -261,7 +264,7 @@ cdef class EventDispatcher(object):
'''
return self.__properties[name]
- cpdef dict properties(self):
+ cpdef dict properties(EventDispatcher self):
'''Return all the properties in that class in a dictionnary of
key/property class. Can be used for introspection.
@@ -270,7 +273,7 @@ cdef class EventDispatcher(object):
cdef dict ret, p
ret = {}
p = self.__properties
- for x in self.__dict__['__storage'].keys():
+ for x in self.__storage:
ret[x] = p[x]
return ret
View
@@ -1,22 +1,24 @@
+from kivy._event cimport EventDispatcher
+
cdef class Property:
cdef str _name
cdef int allownone
cdef public object defaultvalue
- cdef init_storage(self, object obj, dict storage)
- cpdef link(self, object obj, str name)
- cpdef link_deps(self, object obj, str name)
- cpdef bind(self, obj, observer)
- cpdef unbind(self, obj, observer)
+ cdef init_storage(self, EventDispatcher obj, dict storage)
+ cpdef link(self, EventDispatcher obj, str name)
+ cpdef link_deps(self, EventDispatcher obj, str name)
+ cpdef bind(self, EventDispatcher obj, observer)
+ cpdef unbind(self, EventDispatcher obj, observer)
cdef compare_value(self, a, b)
- cpdef set(self, obj, value)
- cpdef get(self, obj)
- cdef check(self, obj, x)
- cdef convert(self, obj, x)
- cpdef dispatch(self, obj)
+ cpdef set(self, EventDispatcher obj, value)
+ cpdef get(self, EventDispatcher obj)
+ cdef check(self, EventDispatcher obj, x)
+ cdef convert(self, EventDispatcher obj, x)
+ cpdef dispatch(self, EventDispatcher obj)
cdef class NumericProperty(Property):
- cdef float parse_str(self, object obj, value)
- cdef float parse_list(self, object obj, value, str ext)
+ cdef float parse_str(self, EventDispatcher obj, value)
+ cdef float parse_list(self, EventDispatcher obj, value, str ext)
cdef class StringProperty(Property):
pass
@@ -44,11 +46,11 @@ cdef class OptionProperty(Property):
cdef class ReferenceListProperty(Property):
cdef list properties
- cpdef trigger_change(self, obj, value)
+ cpdef trigger_change(self, EventDispatcher obj, value)
cdef class AliasProperty(Property):
cdef object getter
cdef object setter
cdef list bind_objects
cdef int use_cache
- cpdef trigger_change(self, obj, value)
+ cpdef trigger_change(self, EventDispatcher obj, value)
Oops, something went wrong.

0 comments on commit 3307572

Please sign in to comment.