Sunday, September 11, 2011

A Grails template rendering profiler

A complex grails page if often a cascade of templates rendering, nested in each others.
Optimizing page views starts with profiling which template takes time and which template is called by which one.
We offer a capture mechanism of all calls and several rendering: call stack, template time summary, and a visual display of the call graph.

grails install-plugin profile-template

By default, all template calls are captured if the plugin is installed in your application. It is possible to deactivate the capture at start in your grails-app/conf/Config.groovy with:

Accessing the data
A controller allows to interact with the profiling data: start/stop capture, clear all events and make reports:
All template events captured can be displayed from several point of views.
Call Stack
A list of calls of template rendering, where the indentation shows the nesting levels

A summary by template name
Where total and intrinsic duration are displayed ("intrinsic" means it is the time taken by the template itself minus the children times)

A call graph
Which template is called by which one? How many times? What is the sum of intrinsic duration for each template. This information is shown via a graphe, thanks to cytoscape.

How does it work?
Well, it is rather simple:
  • the plugin PluginTemplateGrailsPlugin.groovy file contains a doWithDynamicMethods closure. This closure captures start & stop template rendering through StopWatchEvents, store into a service ProfileTemplateService.
  • This service simply store the events by requests. They are store in memory, not to create any domain class and interfere with the host application.
Of course, as any profiling, it is not clever to use the plugin into the production application, nor to let the profiling capture last for too long.

Have fun profiling and don't hesitate to ask any question


  1. Thanks for creating the plugin, may I know can I use this profiler for dynamic templates? Please see

  2. I do not know?
    have you tried straight?
    In fact the "catching" happens in the file ProfileTemplateGrailsPlugins.groovy, where we have:

    def metaGPWClass = org.codehaus.groovy.grails.web.pages.GroovyPageWritable.class.metaClass
    metaGPWClass.invokeMethod = { name, args ->

    If it does not catch dynamic template, we shall find out the method called to render them and insert it at the same position


  3. Hi- the stricter GSP parsing in Grails 2.01 seems to hit a snag on the plugin. Have you noticed this? Thanks.

    C:\Users\winklerj\.grails\2.0.1\projects\suwebsite\gspcompile\gsp_profileTemplate_profileTemplateReport_index_gsp.groovy: 96: unexpected token: name @ line 96,
    column 6.
    for( name, details in (summaryByTemplate) ) {

  4. Hi Jeff,

    that was related to a .. which does not work anymore

    Fix is done and plugin released. Can you give it a try please?
    (version was not updated, so you might have to remove local zip)

  5. This comment has been removed by a blog administrator.

  6. This comment has been removed by the author.

  7. Hi Alexandre,

    I have installed your profile-template plugin. When I go to the http://localhost:8080//profileTemplateReport page, I see the link at the top and press the "start_recording" link and go back to my app and do a few things. When I come back to the ProfileTemplateReport page and press the "view_call_stack" link, nothing appears. I put breakpoints in the ProfileTemplateReportController, so I can see that the code there is executing. I put a breakpoint in the ProfileTemplateService.record() method, but it never seems to get called.

    Is there some configuration step I've missed? All I did to install this was to type "grails install-plugin profile-template" and that worked fine.

    Thanks for your help.


  8. Hei,
    I've not used the plugin with recent grails version. That might be the reason.
    Is it easy for you to have it a go with 1.3.x?

    1. No, I have to use grails 2.0.1. If source was available I might be able to see what's going on.