Edgewall Software

Changes between Version 8 and Version 9 of GSoC2008


Ignore:
Timestamp:
Jul 13, 2008, 4:43:12 PM (16 years ago)
Author:
mkurczych
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • GSoC2008

    v8 v9  
    1313Still need to add some tests covering more situations.
    1414
     15=== Simple pre-rendering ===
     16
     17py:optimize directive was introduced.                                       
     18It marks subtree of this tag as optimizable - which means that rendering code inside can be omited and instead replaced by inserting cached one. In particular it cannot have any Python code that has side effects and cannot depend on variables.                                 
     19
     20Fragment of stream will be replaced by one event saying it represents this code. It will not be unpacked untill it is needed. Following cases "need" unpacking of fragment:                                                   
     21 * matching tag inside optimized fragment; it also applies to first tag in
     22 fragment so instead of                                                   
     23{{{                                                                       
     24<py:match path="foo">                                                     
     25    <bar>                                                                 
     26        ${select('.')}                                                   
     27    </bar>                                                               
     28</py:match>                                                               
     29<foo py:optimize="">                                                     
     30    <p>Some text inside with <i>tags</i> which processing could be costful,
     31    but <b>could be avoided</b> by caching.</p>                           
     32    <p>Next paragraph.</p>                                                 
     33</foo>                                                                     
     34}}}                                                                       
     35one should use                                                             
     36{{{                                                                       
     37<py:match path="foo">                                                     
     38    <bar>                                                                 
     39        ${select('.')}                                                     
     40    </bar>                                                                 
     41</py:match>                                                               
     42<foo>                                                                     
     43    <py:optimize vars="">                                                 
     44    <p>Some text inside with <i>tags</i> which processing could be costful,
     45    but <b>could be avoided</b> by caching.</p>
     46    <p>Next paragraph.</p>
     47    </py:optimize>
     48</foo>
     49}}}
     50 * using Transformer filter; yeah it's really cool, but too cool to be cached - it is able to do nearly anything to the stream
     51 * using form HTMLFormFiller; but here it's better than in Transformer case, because if filter sees there were no forms in fragment it returns just one event for fragment - does not return unpacked version
     52
     53Using filters:
     54 * When filtering stream with filters defined in genshi.output filter object you '''have to''' use the same filter object (don't construct it every time), if you don't optimization engine won't treat result fragment as the same as generated with other filter object
     55 * HTMLFormFiller can be different object
     56
     57
    1558== Currently working at: ==
    1659=== Template pre-processing ===
    17 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.
    18 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.
    19 There's also need of making filters compatible with this changes - probably somehow mark fragment of code they change.
    20 
    21 Sometimes template creator will have to think about optimizations while creating template. For example in following code:
    22 
     60 * make py:optimize take argument -- expression that calculates some "digest" of context variables which this fragment depends on; it can be any hashable python object with assumption, that if results are the same, then the
     61  rendered fragments will be the same
    2362{{{
    24 <a href="/edit/1" py:if="user.authorized()">[edit]</a>
    25 <p>1111 11 11</p>
    26 <a href="/edit/2" py:if="user.authorized()">[edit]</a>
    27 <p>222 22 22 2</p>
    28 <a href="/edit/3" py:if="user.authorized()">[edit]</a>
    29 <p>333 33333 33 333</p>
     63<div py:optimize="var%6">
     64    <py:choice ="var%3">
     65        <p py:when="0">It is divisible by three!</p>
     66        <p py:default="">It's remainder when dividing by three is
     67        ${spell(var%3)}.</p>
     68    </py:choice>
     69    <p py:if="var%2 == 0">It is odd.</p>
     70    <p py:if="var%2 == 1">It is even.</p>
     71</div>
    3072}}}
    31 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:
    32 {{{
    33 <py:with vars="a = user.authorized()">
    34 <a href="/edit/1" py:if="a">[edit]</a>
    35 <p>1111 11 11</p>
    36 <a href="/edit/2" py:if="a">[edit]</a>
    37 <p>222 22 22 2</p>
    38 <a href="/edit/3" py:if="a">[edit]</a>
    39 <p>333 33333 33 333</p>
    40 </py:with>
    41 }}}
    42 Now fragment depends only on variable "a", which can be only True or False, which gives optimization possibilities.
    43 
    44 Or it should be even vars = "a = bool(user.authorized())" to avoid things like that:
    45 
    46 {{{
    47 >>> class Foo(object):
    48 ...     def __len__(self):
    49 ...             print "Sideeffect"
    50 ...             return 1
    51 ...
    52 >>> f = Foo()
    53 >>> if f:
    54 ...     print "Something"
    55 ...
    56 Sideeffect
    57 Something
    58 }}}
    59 
    60 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. :-)