A New Frontier
The Optimising DotLiquid series is so far off to a very promising start. With the core classes significantly improved, its now time to optimise the DotLiquid featureset as a whole, and that means I need a new test template.
The New Template
The new template is designed to incorporate all flow control, iteration and variable tags. A number of different parameter variations for each tag have also been included.
It's ugly, but it does the job:
{% for x in (1..5) %} <h1>Tests all except filters</h1> Also doesn't use INCLUDE or EXTENDS, to be tested later <div> <h2>Variable Tags</h3> <h3>Assign</h3> {% assign handle = 'cake' -%} {{ handle }} <h3>Capture</h3> {% capture my_variable %}I am being captured.{% endcapture -%} {{ my_variable }} </div> <div> <h2>Control Flow Tags</h2> <h3>Case (non-else)</h3> {% case handle -%} {% when 'cake' -%} This is a cake {% when 'cookie' -%} This is a cookie {% else -%} This is not a cake nor a cookie {% endcase -%} <h3>Case (else)</h3> {% case handle -%} {% when 'a' -%} This is a cake {% when 'b' -%} This is a cookie {% else -%} The else statement was reached {% endcase -%} <h3>If equals (non-else)</h3> {% if user.name == 'Steve Jackson' -%} Equals failed on match {% elsif user.name == 'Steve Lillis' -%} Equals was a success {% else -%} Equals failed to else {% endif -%} <h3>If not equals (non-else)</h3> {% if user.name != 'Steve Jackson' -%} Not equals was a success {% else -%} Not equals failed {% endif -%} <h3>If (else)</h3> {% if user.name == 'Steve Jackson' -%} Unexpected user {% else -%} Else body reached {% endif -%} <h3>Unless</h3> {% unless user.name == 'Steve Jackson' -%} Unless worked {% else -%} Unless failed {% endunless -%} </div> <div> <h2>Iteration Tags</h2> <h3>For (with cycle)</h3> {% for item in user.items -%} {% cycle 'one', 'two', 'three' %}: {{ item.description }} {% endfor -%} <h3>For (reversed)</h3> {% for item in user.items reversed -%} {% cycle 'one', 'two', 'three' -%}: {% if item.description == 'First Item' -%} {{ item.description | upcase -}} {% else -%} {{ item.description -}} {% endif -%} {% endfor -%} <h3>For (Limit: 2)</h3> {% for item in user.items limit:2 -%} {% cycle 'one', 'two', 'three' %}: {{ item.description }} {% endfor -%} <h3>For (Offset: 2)</h3> {% for item in user.items offset:2 -%} {% cycle 'one', 'two', 'three' %}: {{ item.description }} {% endfor -%} <h3>For Range</h3> {% for i in (1..4) -%}{{ i -}}, {% endfor -%} <h3>For Range (Continue on 2)</h3> {% for i in (1..4) -%} {% if i == 2 %} {% continue %} {% endif %} {{ i -}}, {% endfor -%} <h3>For Range (Break on 2)</h3> {% for i in (1..4) -%} {% if i == 2 %} {% break %} {% endif %} {{ i -}}, {% endfor -%} <h3>Table Row (Cols:2, Limit:4)</h3> <table> {% tablerow item in user.items cols:2 limit:4 %} {{ item.Description }} {{ item.Cost }} {% endtablerow %} </table> </div> {% endfor %}
Initial Timings
The below timings were all taken during the same time period on the same machine. They are based on 10,000 iterations per test.
Render Time (ms) | Original Code | With Optimisations |
---|---|---|
Minimum | 15.89480 | 6.52180 |
Maximum | 20.14610 | 8.96140 |
Range | 4.25130 | 2.43960 |
Average | 16.35774 | 6.76287 |
Std. Deviation | 0.42730 | 0.20170 |
Summary
The optimisations made thus far have had a distinct impact but ~6.8 milliseconds to render is still much higher than I'd like, especially if a reduced render time is only a few minor improvements away.
In the next post ill be overhauling how the break and continue keywords are implemented in DotLiquid, as I've noticed that they're currently using exceptions to control program flow.
No comments:
Post a Comment