-
Notifications
You must be signed in to change notification settings - Fork 41.2k
Embedded tomcat+jsp: unrequired JSP recompilation causes performance loss #2825
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Thanks for the reproduction |
Part of the problem was gh-2826 which meant that, when checked, the JSP was always thought to have change and it was being recompiled. Fixing this has reduced that after JSP rendering time by an order of magnitude. It still takes longer than the mvn spring-boot:run case as it takes longer to check the JSP and the jars it depends upon (JSTL, etc) when they're nested in a JAR vs when they're available directly on the filesystem. The second part of the problem is that this checking is being performed at all. This is because, as noted above, the |
Thanks, good to see I was on to something. The above slowdown we observe with one tiny JSP page. In my actual app I see a slowdown of about 2 sec (as opposed to the .114 sec above). The page contains some jsp-includes+taglibs etc. That makes performance unacceptable. |
We may have to wait for 1.3 to make the JSP servlet's init parameters configurable via @Bean
public EmbeddedServletContainerCustomizer servletContainerCustomizer() {
return new EmbeddedServletContainerCustomizer() {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
if (container instanceof TomcatEmbeddedServletContainerFactory) {
customizeTomcat((TomcatEmbeddedServletContainerFactory)container);
}
}
private void customizeTomcat(TomcatEmbeddedServletContainerFactory tomcatFactory) {
tomcatFactory.addContextCustomizers(new TomcatContextCustomizer() {
@Override
public void customize(Context context) {
Container jsp = context.findChild("jsp");
if (jsp instanceof Wrapper) {
((Wrapper)jsp).addInitParameter("development", "false");
}
}
});
}
};
} |
Brilliant, thank you! |
Note that in Spring Boot 1.1.7 we did not observe this issue. When we updated our application to Spring Boot 1.2.2, there was a sizable performance loss. Therefore we view it as a regression. Nothing was changed in our application except for the updated library versions. We tracked it down to Jasper performing a recompile on every page load. Our application supports using precompiled jsps, so we were able to compare performance times when the jsps were not precompiled. When not precompiled, the performance loss is extremely significant. Sure, we can we avoid the problem by disabling the JspServlet development mode as mentioned previously, although we view this is a workaround and do not believe it should be considered a solution. Thanks for your help! |
I think they have a real solution slated for 1.3.x so making do with this workaround is acceptable to me until then. |
@wilkinsona: Thank you! :) |
Any chance to have this toggle set to false and set true via spring-boot-devtools? |
@hennr We could certainly consider it, but the suggestion's likely to get lost on a closed issue. Could you open a new one please? |
Great, here is the new issue #7039 |
I ported an existing Spring-MVC+JSP app to Spring Boot and came across this issue.
Jasper intermittently recompiles my JSP pages, causing a loss in performance.
To reproduce:
git clone https://github.com/hanswesterbeek/jsp-compilation-problem
cd jsp-compilation-problem
mvn package;java -jar target/jsp-compilation-problem-0.0.1-SNAPSHOT.war
System.out
As expected, the first view is slow, the JSP must be compiled. When you do a quick reload, it is fast. So far so good.
But if you wait a couple of seconds, or do some browser reloads in quick succession, Jasper is triggered to recompile the JSP page. I suspect it has lost track of the compiled version of the JSP.
In the output below the problem is observed where we read +- 140 ms 'after rendering' :
I don't have a workaround as I can't find a way of setting the Servlet engine 'development' mode to false (it defaults to true). Or perhaps it is better to keep deploying into a regular Tomcat? In that case the documentation should perhaps not say "i.e. an executable war will work" in section 26.3.4 JSP limitations.
This problem does not occur when executing
mvn spring-boot:run
which is why I only noticed it after deploying and actually running withjava -jar
. When running via maven this log message does NOT appear:2015-04-15 11:55:55.735 WARN 96817 --- [ main] .i.s.PathMatchingResourcePatternResolver : Skipping [/Users/hw/Desktop/jsp-compilation-problem/target/jsp-compilation-problem-0.0.1-SNAPSHOT.war] because it does not denote a directory
Note: I'd never have used JSP if it wasn't already present in the app...
The text was updated successfully, but these errors were encountered: