Edgewall Software

Version 8 (modified by mkurczych, 10 years ago) (diff)


Google Summer of Code 2008

The plan

  • Reimplement XPath
  • Add some kind of pre-rendering of parts that don't use variables
  • Try compiling templates to Python bytecode
  • Try adding some minor optimizations

What has been done

XPath reimplementation

Current XPath implementation in Genshi is rather buggy (for example http://genshi.edgewall.org/ticket/185). I've rewritten it. Implemented algorithm works in O(qn) time, where q is length of XPath expression, n is number of stream events and O(qh) memory complexity, where h is height of document XML tree. It computes for every node which places of XPath expression does it match. O(qn) is pessimistic complexity, I think algorithm will work like O(n) in most cases (the worst case is when nearly every node matches to nearly every place of expression, which is quite rare).

Still need to add some tests covering more situations.

Currently working at:

Template pre-processing

There are many templates where much of code doesn't depend on context. It can be pre-rendered once and then only pasted as result. Also common situation is when there are only few possible variable values - for example only True or False. We can pre-reder parts of code for each of values and use them later. We only have to check for given fragment of template which values does it use and find recurrences of this values. There's also need of making filters compatible with this changes - probably somehow mark fragment of code they change.

Sometimes template creator will have to think about optimizations while creating template. For example in following code:

<a href="/edit/1" py:if="user.authorized()">[edit]</a>
<p>1111 11 11</p>
<a href="/edit/2" py:if="user.authorized()">[edit]</a>
<p>222 22 22 2</p>
<a href="/edit/3" py:if="user.authorized()">[edit]</a>
<p>333 33333 33 333</p>

The variable here is user. Creating pre-render dict user -> pre-rendered paragraph wont't help a lot, because there will be a lot of users. But this code can be also written as:

<py:with vars="a = user.authorized()">
<a href="/edit/1" py:if="a">[edit]</a>
<p>1111 11 11</p>
<a href="/edit/2" py:if="a">[edit]</a>
<p>222 22 22 2</p>
<a href="/edit/3" py:if="a">[edit]</a>
<p>333 33333 33 333</p>

Now fragment depends only on variable "a", which can be only True or False, which gives optimization possibilities.

Or it should be even vars = "a = bool(user.authorized())" to avoid things like that:

>>> class Foo(object):
...     def __len__(self):
...             print "Sideeffect"
...             return 1
>>> f = Foo()
>>> if f:
...     print "Something"

Foo can also change its internal state, and return different values in different ifs, which is not good. Only when variable is pure bool (a.class is bool) we are safe. :-)