Hi folks,
We (Oyster.com) use web.ctx attribute access heavily in our template
rendering for internationalization (our version of gettext accesses
web.ctx.locale to look up the user's language, and we call gettext() with
each UI string we need to translate). At present web.ctx is a ThreadedDict,
which is a roll-your-own thread-local dict class. I found that by
subclassing ThreadedDict from Python's built-in
threading.local<http://docs.python.org/library/threading.html#threading.local>class
it speeds up web.ctx attribute access by a factor of 50 or so, which
in turn speeds up our template rendering by about 30% (fairly significant).
Here are timings for original vs new (using threading.local). 4.41 / 0.0835
= 53x as fast.
C:\>python -m timeit -n 1000000 -s "import web; d =
web.utils.OldThreadedDict(); d.x = 1" "d.x"
1000000 loops, best of 3: 4.41 usec per loop
C:\>python -m timeit -n 1000000 -s "import web; d =
web.utils.ThreadedDict(); d.x = 1" "d.x"
1000000 loops, best of 3: 0.0835 usec per loop
So I propose ThreadedDict is changed to inherit from Python's
threading.local. This was added in Python 2.4 -- what Python versions is
web.py supposed to run on? If you need to support pre-2.4 versions, you
could always use threading.local if it exists, otherwise revert to the
existing version.
Below is our version of ThreadedDict (it's somewhat verbose with all those
methods, just so I'm fully emulating a dict).
Thanks,
Ben.
-----
class ThreadedDict(threading.local):
"""Thread local storage.
>>> d = ThreadedDict()
>>> d.x = 1
>>> d.x
1
>>> import threading
>>> def f(): d.x = 2
...
>>> t = threading.Thread(target=f)
>>> t.start()
>>> t.join()
>>> d.x
1
"""
# Define all these methods to more or less fully emulate dict --
attribute access
# is built into threading.local.
def __len__(self):
return len(self.__dict__)
def __getitem__(self, key):
return self.__dict__[key]
def __setitem__(self, key, value):
self.__dict__[key] = value
def __delitem__(self, key):
del self.__dict__[key]
def __contains__(self, key):
return key in self.__dict__
has_key = __contains__
def clear(self):
self.__dict__.clear()
def copy(self):
return self.__dict__.copy()
def get(self, key, default=None):
return self.__dict__.get(key, default)
def items(self):
return self.__dict__.items()
def iteritems(self):
return self.__dict__.iteritems()
def keys(self):
return self.__dict__.keys()
def iterkeys(self):
return self.__dict__.iterkeys()
iter = iterkeys
def values(self):
return self.__dict__.values()
def itervalues(self):
return self.__dict__.itervalues()
def pop(self, key, *args):
return self.__dict__.pop(key, *args)
def popitem(self):
return self.__dict__.popitem()
def setdefault(self, key, default=None):
return self.__dict__.setdefault(key, default)
def update(self, *args, **kwargs):
self.__dict__.update(*args, **kwargs)
def __repr__(self):
return '<ThreadedDict ' + dict.__repr__(self.__dict__) + '>'
__str__ = __repr__
--
You received this message because you are subscribed to the Google Groups
"web.py" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/webpy?hl=en.