cancel
Showing results for 
Search instead for 
Did you mean: 

Slow performance of Freemarker Templates

alr
Champ in-the-making
Champ in-the-making
Hello

I've run into a serious performance problem with my freemarker templates, when rendering a document. This is my szenario:

1. One document, which has an association to seven other documents
2. These seven documents each have associations to 1-3 other documents.

Each association gets looked up and I do an <#include> for each associated NodeID.

This all works, but it is painfully slow. I have summed up below 20 includes, which are nested into 3 levels. Sometimes rendering takes 3 seconds, sometimes even 5. If I deliver the same content I collect with the associations statically, it's a fraction of a second and the content gets delivered. So it must be in some context with the associations or the alfresco content model.

Furthermore I am using my own content model. Can I speed up something by setting indices or stuff like that? I have right now no real idea where to start to search performance hogs. So any hint is a good hint 🙂


Regards,
  Alexander
4 REPLIES 4

alr
Champ in-the-making
Champ in-the-making
Hello

I have made some advances in finding the bottleneck. The bottleneck was a self written function:

<#function loadNode nodeID>
   <#return companyhome.nodeByReference["workspace://SpacesStore/" + nodeID]>
</#function>

This function is incredibly slow. When rendering my freemarker template I am calling this function quite often. In my szenario I can be sure, that the data does not change anymore when it is accessed via this template. So the most simple solution is to create a cache. This is what I did, I implemented my own "getNodeFromCache" freeMarker function in Java, which caches classes from type "TemplateNode" in a HashMap. Here are some numbers to compare:

In my test I call loadNode() with exactly the same node id several times (showing with the amount of iterations)

10 iterations: 609 ms
20 iterations: 1.141 ms
50 iterations: 3.437 ms
100 iterations: 5.890 ms
250 iterations: 14.670 ms
500 iterations: 30.543 ms
750 iterations: 43.980 ms
1.000 iterations: 55.525 ms
2.000 iterations: 79.600 ms

In my second test I call my caching getNodeFromCache function, which looks up first in its own cache and if it is not found, it does the same lookup then companyhome.getNodeByReference()

10 iterations: 0 ms
20 iterations: 15 ms
50 iterations: 31 ms
100 iterations: 63 ms
250 iterations: 156 ms
500 iterations: 297 ms
750 iterations: 437 ms
1.000 iterations: 594 ms
2.000 iterations: 1.250 ms

This was the first of my found bottlenecks. I am now up to 7-9 requests per second (about 20 times faster than before), which is ok, but not yet good enough for my use case.

The next thing I would like to cache, is a call like <#include> (or at least implement some prerendering functionality), however this is a freemarker core call, so I am not sure, whether this is the way to go. The first thing I would like to know (as I have not found it yet in the source) is, why can you do something like

<#include "workspace://SpacesStore/" + freeMarkerContainerTemplateID>

This implies, that the include call is overwritten in the Alfresco Repository, as you are not able to use a NodeID by default, or? Any pointers in the right direction are appreciated. Thanks! 🙂


–Alexander

loftux
Star Contributor
Star Contributor
I have a document report that iterates spaces. If this is run inline (to be renderd within the webclient) it takes about 30-45 seconds. If I call the template and shows it outside of the webclient it wil render in 5-10 seconds.

To do this I have a  fremarker template inline with links
<a href="/alfresco/template/?templatePath=/Company%20Home/Data%20Dictionary/Presentation%20Templates/Document_Report.ftl&contextPath=${space.displayPath}/${space.properties.name}" target="_blank"  >Full document report</a>

Clicking that link, and it will display a new window with only your freemarker output. Try this and see if you get the same performance improvement.

alr
Champ in-the-making
Champ in-the-making
Hi

I am already outside of the webclient and rendering my freemarker template with the GuestTemplateServlet calling like


http://localhost:8080/alfresco/guestTemplate?templatePath=/Company%20Home/Data%20Dictionary/Presenta...


–Alexander

alr
Champ in-the-making
Champ in-the-making
Hello,

again replying to my own post, but I found out something interesting, which might be a bug in freemarker (already inserted at http://sourceforge.net/tracker/index.php?func=detail&aid=2417204&group_id=794&atid=100794).

I am not too sure where the problem ist, but when I remove commentaries (which include other freemarker commands, like <#– <#return foo –>) and newlines out of my template, it runs significantly faster. But this problem bursts, when I try to access the same freemarker template with several HTTP clients at the same time. Then each template needs more time rendering (the time to  render increases with each parallel http request). This smells like some synchronization problem, but I cannot track this down for sure.

I also wrote an own FreeMarkerProcessor.java class, which does not use any caching mechanism in order to sort this problem out - but it did not change anything.

I hope to get some feedback from the freemarker people, but if any of the developers might know some bottleneck in context of concurrency and parsing time (any synchronized parts during parsing/rendering), feel free to speak up, so we could try to sort this problem out.

However I am now up to 20 requests per second, when there are more than two parallel connections, which is a fair value (but who knows, perhaps it can still be pushed). Two parallel connections might be handled by the Pentium4 CPU with Hyperthreading which it runs on (meaning two truly parallel running threads), so it might not be possible to be any quicker?


Regards,
Alexander