UPDATE:
Play 1 module available here: https://github.com/mbknor/faster-groovy-templates
Play 2 module available here: https://github.com/mbknor/gt-engine-play2
Why re-implement the Groovy Template Engine?
Play Framework version 1.x default template engine is based on Groovy. Play 2.0 has a new template system based on Scala but we want to make it possible to migrate from Play 1.x to 2.0 without having to rewrite all of your old Groovy Templates.
When investigating how to use the Groovy template engine code from Play 1.x in Play 2.0 it turned out to be difficult since the implementation is really tight coupled with the entire Play 1.x code base.
This made me start a (too big) project to re-implement the entire Groovy Template Engine making sure it was not using any of the other Play code. This would make it possible to use the exact same implementation in Play 2.0. It aims to be 100 % compatible with existing templates/applications.
When doing this reimplementation I have managed to make it faster (and using a little less memory i think 🙂 ). I’ll probably write another blogpost later about how it is implemented but basically I precompile the template source down to both java and as little groovy code as possible. See at the bottom for benchmark results.
I think the new implementation is feature-complete (But Beta) and we’re using it in development at work. But there is still work to do:
- checking/making sure I have not broken too much api 🙂
- improve/clean api/code
- Moving the code to external project so Play only uses a jar-file
- Add code to Play 2.0 to use the groovy engine.
(New feature: If you add ‘save-gttemplate-source-to-disk = true’ to application.conf, the generated java and groovy source code is dumped to disk so you can step-debug it if you want.)
The current source (Based on Play 1.2.4-RC2) can be found https://github.com/mbknor/play/tree/new_groovy_template_impl (UPDATE: Remember to use the correct branch ‘new_groovy_template_impl’).
Please try it out and report any problems or suggestions/thoughts.
Some limitations regarding Groovy code snipits %{ ..code.. }%:
Benchmark
The following benchmark results are not scientific at all but I made them just to try to show the difference between old and new implementation. It is based on Play 1.2.4-RC2.
The test application can be found at github
This is how I performed the tests
I started Play like this: play run –%prod -XX:CompileThreshold=10
I used CompileThreshold to shorten the needed jvm warm up time.
For each speed-benchmark i restarted play, ran 14000 request using ab (40 concurrent), then did another 14000 request and recorded the stats.
For memory-benchmarks I restarted Play, then recorded heap usage with jvisualvm during the first 14000 requests. All GC settings are default.
Detailed info about the speed benchmark can be found here.
Google spreadsheet with useful numbers can be found here.
Each test shows two numbers:
- requests pr second
- total “rendering time” for all 14000 requests. (total time for test minus total time for noTemplate-test: Shows aprox time spent with rendering without time spent in framework itself)
minimalTemplate
ab -k -c 40 -n 14000 http://localhost:9000/application/minimalTemplate
Requests pr second
1.2.4-rc2 |
6526 r/s |
new impl |
7141 r/s |
Improvement |
1.09X |

Total “Rendering time”
1.2.4-rc2 |
0.362 seconds |
new impl |
0.208 seconds |
Improvement |
1.74X |

normalTemplate
ab -k -c 40 -n 14000 http://localhost:9000/application/normalTemplate
Requests pr second:
1.2.4-rc2 |
1674 r/s |
new impl |
2801 r/s |
Improvement |
1.67X |

Total “Rendering time”
1.2.4-rc2 |
6.57 seconds |
new impl |
3.24 seconds |
Improvement |
2.03X |

normalTemplateBigData
ab -k -c 40 -n 14000 http://localhost:9000/application/normalTemplateBigData
Requests pr second:
1.2.4-rc2 |
323 r/s |
new impl |
524 r/s |
Improvement |
1.62X |

Total “Rendering time”
1.2.4-rc2 |
41.438 seconds |
new impl |
24.935 seconds |
Improvement |
1.66X |

normalTemplateBigDataWithJavaExtensions
ab -k -c 40 -n 14000 http://localhost:9000/application/normalTemplateBigDataWithJavaExtensions
Requests pr second:
1.2.4-rc2 |
290 r/s |
new impl |
434 r/s |
Improvement |
1.50X |

Total “Rendering time”
1.2.4-rc2 |
46.336 seconds |
new impl |
30.464 seconds |
Improvement |
1.52X |

normalTemplateBigDataInTag
ab -k -c 40 -n 14000 http://localhost:9000/application/normalTemplateBigDataInTag
Requests pr second:
1.2.4-rc2 |
310 r/s |
new impl |
460 r/s |
Improvement |
1.48X |

Total “Rendering time”
1.2.4-rc2 |
43.236 seconds |
new impl |
28.658 seconds |
Improvement |
1.51X |

normalTemplateBiggerData
ab -k -c 40 -n 14000 http://localhost:9000/application/normalTemplateBiggerData
Requests pr second:
1.2.4-rc2 |
35 r/s |
new impl |
56 r/s |
Improvement |
1.60X |

Total “Rendering time”
1.2.4-rc2 |
388.032 seconds |
new impl |
245.809 seconds |
Improvement |
1.58X |

Memory info
normalTemplate
1.2.4-rc2

new impl:

normalTemplateBigData
1.2.4-rc2

new impl:

normalTemplateBigDataInTag
1.2.4-rc2

new impl:

Some last words
I hope this info was useful (It actually took a long time to perform the tests and write this blog 🙂 ). Also, I hope you download the custom play version and help me find problems not yet found.
UPDATE: Play 1 module available here: https://github.com/mbknor/faster-groovy-templates Play 2 module available here: https://github.com/mbknor/gt-engine-play2 Why re-implement the Groovy Template Engine? Play Framework version 1.x default template engine is based on Groovy. Play 2.0...