tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Christopher Schultz <ch...@christopherschultz.net>
Subject Re: Re : Memory leak in Tomcat 6.0.35 ( 64 bit)
Date Tue, 16 Apr 2013 14:31:28 GMT
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Howard,

On 4/15/13 4:02 PM, Howard W. Smith, Jr. wrote:
> On Mon, Apr 15, 2013 at 1:08 PM, Christopher Schultz < 
> chris@christopherschultz.net> wrote:
> 
> Howard,
> 
> On 4/14/13 9:53 PM, Howard W. Smith, Jr. wrote:
>>>> I am definitely relying on  user HttpSessions, and I do
>>>> JPA-level caching (statement cache and query results cache).
>>>> pages are PrimeFaces and primefaces = xhtml, html, jquery,
>>>> and MyFaces/OpenWebBeans to help with speed/performance.  And
>>>> right now, the app handles on a 'few' simultaneous
>>>> connections/users that do small and large fetches/inserts
>>>> from/into relational database. :)
> 
>> You can tune the JPA caching, etc. to meet your environmental
>> needs, etc., so you don't *need* a huge heap. If you find that
>> you need to be able to improve your performance, you might be
>> able to increase your cache size if it in fact improves things.
> 
> doing this, and just made some code changes to tap a little more
> into JPA caching, but one of my endusers just did a user operation
> on one of the pages, and he sent me a screen capture of the nasty
> eclipselink error that he experienced. evidently, i need to tweak
> caching or do not use the cache at that point in the app. :)

Just remember that caching isn't always a worthwhile endeavor, and
that the cache itself has an associated cost (e.g. memory use,
management of the cache, etc.). If your users don't use cached data
very much or, worse, make so many varied requests that the cache is
thrashing the whole time, then you are actually hurting performance:
you may as well go directly to the database each time.

(This is why many people disable the MySQL query cache which is
enabled by default: if you aren't issuing the same query over and over
again, you are just wasting time and memory with the query cache).

> i explained to him that i did some major changes in the app,
> related to caching... and i told him that it was for 'performance
> improvement', and told him the same as Mark just told me, Google is
> your friend (and told him that 'wiki' keyword in the search is your
> friend, too).  :)

You should probably monitor your cache: what's the hit rate versus
miss rate, and the cache turnover. You might be surprised to find that
your read-through cache is actually just a churning bile of bytes that
nobody really uses.

It also sounds like you need a smoke test that you can run against
your webapp between hourly-deployments to production ;) I highly
recommend downloading JMeter and creating a single workflow that
exercises your most-often-accessed pages. You can a) use it for
smoke-testing and b) use it for load-testing (just run that workflow
50 times in a row in each of 50 threads and you've got quite a load,
there).

> i have some things in mind what I want to do with that large
> session scoped data. I am considering caching it at application
> level and all users have ability to update that huge List<> and
> extract data. I was thinking of using @Singleton Lock(READ) to
> control access. it takes no time at all to search the List<> for
> the information that it needs, and it takes no time at all to
> re-populate the List<>.

If you are searching your List<>, perhaps you don't have the right
data structure. What is the algorithmic complexity of your searches?
If it's not better than O(n), then you should reconsider your data
structure and/or searching algorithm.

Does the list need re-population? How often?

> Since we discuss GC a lot on this list, i wonder if you all
> recommend to set the 'list' to null, first, and then List<> ... =
> new ArrayList<>(newList), or new ArrayList<>(newList) is sufficient
> for good GC.

Setting the reference to null is a waste of time as far as the GC is
concerned. When I write code that re-uses the same identifier a lot in
a particular method (e.g. a single PreparedStatement identifier in a
long JDBC transaction executing many statements), I will close the
statement and then set explicitly it to null before continuing. I do
that to ensure that the statement is no longer re-usable due to bad
coding in my part. But it does not really help anything at runtime.

On the other hand, if you have a large data structure that you use
during a part of a method but not all of it, then explicitly setting
the reference to null can help collect the garbage sooner. A
completely contrived example:


List<Id> itemIds = ...;
Map<Id,Item> map = createEnormousMap();
List<Item> items = new ArrayList<>;
for(Id id : itemIds)
  items.add(map.get(id));

// Marker for discussion

for(some long time)
{
  // do some long operation
  // that does not require the "enormous map"
}

return items;

In the above method, if the second loop runs for a long time (relative
to the rest of the method), then explicitly setting "itemIds" to null
in the middle of the method will cause the object pointed to by "map"
to become unreachable and therefore collectable by the GC (assuming
that the map isn't referenced anywhere else, of course) before the
method returns. So, in this case, setting a variable to null *can*
help the GC.

>> I've written a Filter and HttpSession wrapper that can do that
>> kind of thing transparently to the application code. I don't
>> actually use it right now -- it was just a proof-of concept --
>> but it's a quick and dirty way to get caching but also save a
>> safety valve.
> 
> that's nice proof of concept! I guess i've heard so much bad about
> people not cleaning up threadlocals, that I try to avoid usage of
> threadlocal, but it's interesting, so much talk on this list about
> threadlocals, but they threadlocals seem to be used by many
> implementations/software out there. Not naming any names. :)

It's not a ThreadLocal, it just wraps the request so that accesses of
the HttpSession can have WeakReferences transparently wrapped-around
the actual objects. I did it to a) avoid having to re-write a bunch of
code when I wanted to use WeakReferences and b) avoid having to have
that ugly code visible in my actual application code. Since it's an
orthogonal feature (e.g. the application code doesn't have to know
there is an expirable-cache in play... it just knows that it's
recoverable for an object *not* to be available), it's a perfect job
for a Filter an associated wrapper objects.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
Comment: GPGTools - http://gpgtools.org
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIcBAEBCAAGBQJRbWC/AAoJEBzwKT+lPKRY88kP/1jOt9yEHNNJy0b4fcmrNcK8
1mB4DADmvNoW5F+xI56YxjZ3wLP8GK4hkOHRz82eED9qpiCnIvSEfO4mdSFNnVfq
CJOFYNnBmdbDxPea9K52VjJ6lenjN5+gOggrJB1LuImP359pmkW3Xdv/q89OSrph
Q9xf1VPeohv6ANv2eOWZ4zC5L+28LLmkWqJXajfw940MOvBTiSmKi1/Zz9hCuGOQ
XG+QkSxcGUnP2cWqQKkkuIUGOR8iTcwy00STI/i9QxruBooUcMqTBQ4v9YcqTGoN
FXV1mLiIM3oG36XickblLyCAK60Qtvx1PaKAvmFM30XeKAcS2gRmglkDM6yYG311
2TUzHytYVEnZm/6Wet+2VmMdEVqjhwRFOTcegs5VhC6KBoUSJ6W/xNugfJam0DHv
3dF9mZy/6ecL3KKY3c+7hJcQ6b9F79J7MksCvf8YGff+k/Br3Vme9VVzUfEcy572
i6CuAXb9X5uSC/vr1yincyqfNAZoPrabkNExqW8/tGd1YGky92DG/bRxMCxEUlMn
S6k8av3ZXv+neF3kNfkLgynvxD/2MWyK1cO5Q61VZ7jkRx3AqWFcHx3sImh9FW5N
vwVTd7jb8N3gBYegTfeWFN8fGaMp4bLWlpSAoyuvB/M0OXQ+GW3GDasVqt0zxBct
0a25Y6XUHv7bxLPKGNWK
=nLK3
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Mime
View raw message