You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Scott Severtson <ss...@digitalmeasures.com> on 2013/11/01 14:23:06 UTC
Subject: Questions on Jasper's BodyContentImpl, bug #43925, and proposed
solution
All,
We've noticed that our Tomcat 6.0.37 instances have increasing overhead
the longer they stay up. We've captured some heap dumps, expecting to
find memory leaks within our code, but found something different instead.
Jasper's BodyContentImpl is actually holding most of the non-collectible
garbage, in the internal char[] buffer. I've checked trunk of Tomcat 6,
7 and 8, and see that the same implementation is still used, so this
issue applies to all currently supported versions.
This issue appears to be well known:
*
http://stackoverflow.com/questions/10421908/is-there-a-fix-for-bodycontentimpl-jsp-tag-memory-leak-using-tomcat
* https://issues.apache.org/bugzilla/show_bug.cgi?id=43925
Specifically what we see happening is due to large pages being rendered
in JSPs - sometimes in the multi-megabyte range, especially for internal
tools. Apparently, some of the tags we use require buffering the output,
versus sending it directly to the Writer.
Now, we certainly can simply set LIMIT_BUFFER and forget about it (throw
away any buffers larger than 8k), but this isn't optimal for our
application. For about 75% of our requests, ~8k is the baseline page
size, with many larger than that. So, depending how the data size, we
could be reallocating multiple times, only to throw away the buffer at
the end.
We'd like to propose a different behavior, and are wondering what others
think about it. If it sounds like a good idea, we're certainly willing
to submit patches to implement it.
--Proposal--
Instead of a hard-coded DEFAULT_TAG_BUFFER_SIZE of 8k, make it
configurable. In addition, if LIMIT_BUFFER is set, provide another
configurable setting called something like MAX_TAG_BUFFER_SIZE (if not
set, defaults to DEFAULT_TAG_BUFFER_SIZE). This would give applications
a more predictable *range* of memory allocated for tag buffers, while
decreasing the frequency of reallocation.
--/Proposal--
We'd probably set DEFAULT_TAG_BUFFER_SIZE to 16k, and set
MAX_TAG_BUFFER_SIZE to either 64k or 128k, based on real-world
performance testing.
One other, slightly less defined question - is there a reason we're
managing char arrays ourselves, instead of using something like Java's
StringBuilder or Javalution's TextBuilder? StringBuilder would reduce
code maintenance, while something like TextBuilder would also reduce
array allocation.
We'd love to hear your thoughts.
Thanks,
Scott Severtson
Lead Platform Architect
Digital Measures
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: Subject: Questions on Jasper's BodyContentImpl, bug #43925, and proposed solution
Posted by Jeremy Boynes <jb...@apache.org>.
On Nov 1, 2013, at 6:23 AM, Scott Severtson <ss...@digitalmeasures.com> wrote:
> All,
>
> We've noticed that our Tomcat 6.0.37 instances have increasing overhead the longer they stay up. We've captured some heap dumps, expecting to find memory leaks within our code, but found something different instead.
>
> Jasper's BodyContentImpl is actually holding most of the non-collectible garbage, in the internal char[] buffer. I've checked trunk of Tomcat 6, 7 and 8, and see that the same implementation is still used, so this issue applies to all currently supported versions.
>
> This issue appears to be well known:
> * http://stackoverflow.com/questions/10421908/is-there-a-fix-for-bodycontentimpl-jsp-tag-memory-leak-using-tomcat
> * https://issues.apache.org/bugzilla/show_bug.cgi?id=43925
>
> Specifically what we see happening is due to large pages being rendered in JSPs - sometimes in the multi-megabyte range, especially for internal tools. Apparently, some of the tags we use require buffering the output, versus sending it directly to the Writer.
>
> Now, we certainly can simply set LIMIT_BUFFER and forget about it (throw away any buffers larger than 8k), but this isn't optimal for our application. For about 75% of our requests, ~8k is the baseline page size, with many larger than that. So, depending how the data size, we could be reallocating multiple times, only to throw away the buffer at the end.
>
> We'd like to propose a different behavior, and are wondering what others think about it. If it sounds like a good idea, we're certainly willing to submit patches to implement it.
>
> --Proposal--
> Instead of a hard-coded DEFAULT_TAG_BUFFER_SIZE of 8k, make it configurable. In addition, if LIMIT_BUFFER is set, provide another configurable setting called something like MAX_TAG_BUFFER_SIZE (if not set, defaults to DEFAULT_TAG_BUFFER_SIZE). This would give applications a more predictable *range* of memory allocated for tag buffers, while decreasing the frequency of reallocation.
> --/Proposal--
Allowing for a cap on growth and throwing an IOException when it is hit seems like a reasonable precaution to prevent more drastic OOM errors (I've been bitten by this too).
Using a threshold rather than simple boolean to control recycling could be helpful. It could easily mimic the current functionality albeit at the cost of backward compatibility. However, I would expect see allocations gradually creep up to this limit across the board so it seems more predictable just to raise the default to that value.
> We'd probably set DEFAULT_TAG_BUFFER_SIZE to 16k, and set MAX_TAG_BUFFER_SIZE to either 64k or 128k, based on real-world performance testing.
DEFAULT_TAG_BUFFER_SIZE is only 512 bytes and, AIUI, is set low-ish just to cover the common case where fragments generate small amounts of output. I don't think we should change the defaults for these.
> One other, slightly less defined question - is there a reason we're managing char arrays ourselves, instead of using something like Java's StringBuilder or Javalution's TextBuilder? StringBuilder would reduce code maintenance, while something like TextBuilder would also reduce array allocation.
Patches are always welcome.
Cheers
Jeremy