Bug ID: 60146
Summary: Performance issue as CachedResource#getInputStream()
is not caching data correctly
Product: Tomcat 8
Created attachment 34262
Patch that potentially fixes the issue in TC8.5.x and trunk.
The problem is with org.apache.catalina.webresources.CachedResource.java
While getContent() is correctly creating a byte cache if the object is small
enough, getInputStream() is not. This means that if the caller never calls
getContent() before calling getInputStream() no cache is created, and the data
is fetched from the file every time.
This turned out to be a big issue in my performance comparison test against
Tomcat 6 which was indirectly trying to load a Spring properties file that
wasn't getting cached because of this bug.
I could see Tomcat 8 consistently take 3x the memory and almost 1.5x times the
CPU just because the JVM's young-generation space was overwhelmed with dealing
with the temporary java.util.zip.inflater objects that got created while Spring
(which apparently relies only on getInputStream) was trying to read the
It seems that the simplest way to fix this issue is to make getInputStream()
call getContent() first to establish the cache, rather than assume that
getContent() would have been already called. Considering how getContent() is
written, I don't think this will lead to any extra overhead.
I did test this one line change and I could see that the memory and CPU
utilization in Tomcat 8 dropped back to similar levels to Tomcat 6.
I have only tested against Tomcat 8.5.5 but looking at the code it seems that
the issue is also present in trunk.
I am attaching a patch which fixed the issue in my testing. I'm not sure if
there's a better fix or if the patch is in the correct format, but I hope the
patch at least illustrates the underlying issue.
You are receiving this mail because:
You are the assignee for the bug.
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org