Thymeleaf performance degradation

classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

Thymeleaf performance degradation

jackyxuebin
Hi guys,

I am new to thymeleaf and I am facing some serious performance issues. I'm using theymeleaf version 2.1.2

In one of my pages, I am using thymeleaf each loop for displaying items. When I start tomcat server, Thymeleaf takes around 10 seconds to to render a page with 20 items. Then I click on the page again, this time it's taking 20 seconds. The third time I click on this page, thymeleaf take 30+ seconds. The performance is getting worse and worse after each click. I have embeded my log here. Has anyone experienced similar problem before? Thanks in advance.

19:05:55,719 DEBUG "http-bio-8080"-exec-8 thymeleaf.TemplateEngine:1051 - [THYMELEAF]["http-bio-8080"-exec-8] STARTING PROCESS OF TEMPLATE "layout/default" WITH LOCALE en
19:05:55,719 DEBUG "http-bio-8080"-exec-8 thymeleaf.TemplateEngine:1150 - [THYMELEAF]["http-bio-8080"-exec-8] Starting process on template "layout/default" using mode "HTML5"
19:05:56,582 DEBUG Http Connection Cleanup conn.PoolingClientConnectionManager:292 - Closing expired connections
19:05:56,582 DEBUG Http Connection Cleanup conn.PoolingClientConnectionManager:286 - Closing connections idle longer than 10000 MILLISECONDS
19:05:57,147 DEBUG "http-bio-8080"-exec-8 thymeleaf.TemplateEngine:1159 - [THYMELEAF]["http-bio-8080"-exec-8] Finished process on template "layout/default" using mode "HTML5"
19:05:57,150 DEBUG "http-bio-8080"-exec-8 thymeleaf.TemplateEngine:1065 - [THYMELEAF]["http-bio-8080"-exec-8] FINISHED PROCESS AND OUTPUT OF TEMPLATE "layout/default" WITH LOCALE en
19:05:57,150 DEBUG "http-bio-8080"-exec-8 TemplateEngine.TIMER:1071 - [THYMELEAF]["http-bio-8080"-exec-8][layout/default][en][1431288703][1431] TEMPLATE "layout/default" WITH LOCALE en PROCESSED IN 1431288703 nanoseconds (approx. 1431ms)

Regards,
Bin
Reply | Threaded
Open this post in threaded view
|

Re: Thymeleaf performance degradation

Zemi
Administrator
Hello,

Probably the problem is not related to Thymeleaf at all, unless you are doing something very unstandard.

Could you post some code related to this issue? Maybe we can spot the issue in it.

Regards,
  Zemi

Reply | Threaded
Open this post in threaded view
|

Re: Thymeleaf performance degradation

jackyxuebin
This post was updated on .
Hi,

This is the code segment I think might be causing the performance issue. I suspect it could be the heavy logic within this segment? The performance degrades heavily with more items in the loop.
<div th:each="x : ${items}>
<div>
<img th:each="image : ${x.images}" th:src="@{${image.imageUrl}}"></img>
<h5 class="x-title" th:uText="${x.g}">Lorem ipsum dolor sit amet</h5>
<div>
<span th:if="${#lists.contains(x.flag,'a')}">a</span>
<span th:if="${#lists.contains(x.flag,'b')}">b</span>
</div>
</div>
<div>
<div>
<div>
	<div>
		<div>
			<span th:uText="#{market.currency.unit.symbol}+${#numbers.formatDecimal(x.displayPrice,0,'COMMA',price_decimal_digit,'POINT')}" ></span>
		</div>
		<div>
			<th:block th:if="${x.a.b!=null}">
				<a th:href="${x.a.b}" href="#" target="_blank">
					
						<span th:if="${x.a.c!=null}" th:text="${x.a.c}"></span>
						<span th:unless="${x.a.c!=null}" class="text-default" th:utext="#{a}"></span>									
				</a>							
			</th:block>
			<th:block th:if="${x.a.d!=null}">
				<a>								
					<span th:if="${x.a.c!=null}" th:text="${x.a.c}"></span>
					<span th:unless="${x.a.c!=null}" th:utext="#{nutrition.detail.text}"></span>
				</a>
				<div>
					<div>
						<h4 th:text="${x.e}"></h4>
						<div th:utext ="${x.a.d}">
						</div>
					</div>
				</div>
			</th:block>
			<th:block th:unless="${x.a.b!=null or x.a.d!=null}">							
				<span th:if="${x.a.c!=null}" th:text="${x.a.c}"></span>
			</th:block>							
		</div>
	</div>
</div>
<div>
	<a th:if="${x.buttonAction=='a'} " th:href="${a}">a</a>
	<a th:if="${x.buttonAction=='b'} " th:href="@{b}">b</a>
	<a th:if="${x.buttonAction=='c'}" >c</a>
	<a th:if="${x.buttonAction=='d'}" >d</a>
	<a th:if="${x.buttonAction=='e'} " th:href="@{e.html}">e</a>
	<a th:if="${x.buttonAction=='f'}"  >f</a>												
</div>
</div>
</div>
</div>												
Regards,
Bin
                                                                       
Reply | Threaded
Open this post in threaded view
|

Re: Thymeleaf performance degradation

Emanuel
Administrator
I suspect the forum might have eaten your code.  You can put code between <raw></raw> tags so the forum knows to leave it alone.
Reply | Threaded
Open this post in threaded view
|

Re: Thymeleaf performance degradation

danielfernandez
Administrator
In reply to this post by jackyxuebin
Are you calling any kind of business logic inside your iteration? For example, retrieving things from database as they are rendered or something.... maybe a very complex or database-calling "toString()" method or something like that?

Your log says your page renders in 1.43 seconds (not 10 seconds as you say) which is quite a lot. It certainly doesn't look like the problem is in the Thymeleaf side... A thymeleaf page merely iterating 20 elements from a collection would normally render in a millisecond or so...

Your log also shows some warnings related to expired connections... can it be that you are not properly closing your database connections? this would mean you are exhausting your DB connection pool, which makes your threads wait until existing connections time-out. This matches quite well your described scenario of obtaining slower executions each time...

Reply | Threaded
Open this post in threaded view
|

Re: Thymeleaf performance degradation

jackyxuebin
In reply to this post by Emanuel
Hi Emanuel,

Thanks. I have put the code inside the raw tag and I have found the root cause of this problem. Seems it's due to the #list.contains() function. I removed those two functions and the loading time reduced five fold.

Regards,
Bin
Reply | Threaded
Open this post in threaded view
|

Re: Thymeleaf performance degradation

jackyxuebin
Hi Daniel,

I have updated the code. Now it's fully visible. I do have some display logic inside. But no call to database. Sorry I probably have taken the wrong log(it is log for another page). It does take around 10 seconds for 20 items.(each item is complex object with embedded object) After removing the two #lists.contains() method, I managed to load the page within 2 second. But there is still one problem. I deployed this on the server and after one day, the performance of the server degrades significantly. (ie the time taken to load the same page is getting longer and longer).

Regards,
Bin
Reply | Threaded
Open this post in threaded view
|

Re: Thymeleaf performance degradation

danielfernandez
Administrator
Hi again,

Thymeleaf is not caching any of your data, so your performance degradation shouldn't be caused by your execution of the template. The #lists.contains() method uses the "equals()" method in your objects, are they Strings as they look like in your code sample? Maybe their implementation of "equals()" is complex? What implementation of "java.util.List" is "x.flag"? Is it a hibernate or JPA-managed collection? Are your entities being transparently persisted (and therefore their properties being transparently retrieved from DB while you iterate them?)

I ask this because #lists.contains() simply delegates to the "contains" method of your java.util.List implementation, and it's pretty difficult for me to understand how some executions of List.contains(), even with a quite large list, can provoke a 5x execution time difference if your lists are something standard like ArrayList's --which probably are not. So I'm inclined to think your "x" objects are JPA or hibernate entities whose properties are being transparently hydrated during template execution, which is causing your problems. I still think this looks quite a lot like a DB access issue...

Btw... I don't know how many images you have per "x" instance, but your flags seem like they could be computed before iterating the images, not inside the iteration...


Reply | Threaded
Open this post in threaded view
|

Re: Thymeleaf performance degradation

Zemi
Administrator
In reply to this post by jackyxuebin
Hello,

there is nothing in that fragment that should cause it to execute in more than a few milliseconds, so you'll have to look for the problem in your Java code.

Does those x.a.b call some kind of lazy loading (database, web services...)?

Regards,
  Zemi

[Edit: I see Daniel has already pointed in the same direction]
Reply | Threaded
Open this post in threaded view
|

Re: Thymeleaf performance degradation

RedSnappa
In reply to this post by jackyxuebin
Try running it on java 1.7.0_45 or below that might help. I'm having the same problem and that is the only solution I've found so far anyway
Reply | Threaded
Open this post in threaded view
|

Re: Thymeleaf performance degradation

jackyxuebin
Hi,

I actually found out the cause of the slowness. Aside from the two #lists.contains() method, I have some other utility methods such as #map.size() etc. Seems there are some issues with those utility methods. I don't know exactly the root cause of this, but after shifting those method calls to my beans methods, ie (having a attribute declared in my bean instead of using those utility methods to get size etc), everything works fine for me. Hope it helps for people with the same problem.

Regards,
Bin
Reply | Threaded
Open this post in threaded view
|

Re: Thymeleaf performance degradation

jackyxuebin
Hi,

We finally found out the root cause. It was in no way related to thymeleaf. It was actually a Spring memory leak bug. Maybe this can help you as well.

https://jira.spring.io/browse/SPR-11394

We upgraded to Spring 4.1.1 and the problem resolves.

Regards,
Bin
Reply | Threaded
Open this post in threaded view
|

Re: Thymeleaf performance degradation

NightOwl
I just ran into a similar issue. One view, which was very similar to a dozen others and had been working fine, suddenly started taking 15 to 30 seconds to render. It was testing two lists with isEmpty and outputting numerous variables within two sets of nested loops but wasn't doing anything that could possibly take more that 100 milliseconds like most of the other views.

From the log files my java code and database lookups were quickly eliminated as suspects and the trouble area was narrowed down to about 50 lines of code using Thymeleaf pre-processing, expression utility object methods, and some i18n substitutions. Commenting portions of these lines would decrease load times to 4 or 5 seconds but only commenting all of them brought the times back to normal. This persisted through many undeploy / deploy cycles, a few Tomcat stop / start cycles, and deployment to another server.

I wasted many hours debugging, using my most advanced Google Foo, and cursing Thymeleaf for ruining my life (project deliverable due). Then the first result for the simple search phrase "Thymeleaf slowness" brought me here.

Following jackyxuebin's advice I moved from Spring 4.0.0 to 4.1.1 and voila the problem disappeared and my sanity was restored.

Many thanks to jackyxuebin, daniel for all his hard work on Thymeleaf, and all who contributed to this thread. Also, apologies for all the unjust things I may have accused Thymeleaf of during fits of hopelessness and frustration ;-)