EhCache Hibernate L2 cache maxBytesLocalHeap slow
I have a pretty standard persistence tier setup in my managed Spring application using Hibernate (4.2.15.Final) with EhCache (2.6.9) as the second tier cache.
Everything works as expected. However, it sometimes takes a long time to enter entries into the L2 cache.
I have configured my domain model classes to be cached in an explicit file
(I have not configured the default cache):
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" name="hibernate" updateCheck="false" monitoring="autodetect" dynamicConfig="false" maxBytesLocalHeap="300M" maxBytesLocalDisk="500M"> <cache name="org.mycorp.model.MyEntity" eternal="true" overflowToDisk="false" diskPersistent="false" maxBytesLocalHeap="5M" /> ... </ehcache>
I get the following INFO message logged when the persistence context starts up:
DefaultSizeOfEngine | using Agent sizeof engine
and the following WARNING at runtime
ObjectGraphWalker | The configured limit of 1,000 object references was reached while attempting to calculate the size of the object graph. Severe performance degradation could occur if the sizing operation continues. [...]
should evaluate cache-placed objects because I configured separate cache areas with
My domain model is quite complex and I know I can restrict the movement of the graph to annotations
, but I don't know how to solve the problem:
- Do I need to ignore one side of a bidirectional association to avoid loops?
- Should I explicitly ignore the transition elements of the domain model classes?
- In general, is it wise to go with
when using EhCache along with Hibernate, or should I settle for
because Hibernate keeps a separate cache area for each object?
[UPDATE] . I found that transient members would not be cached by Hibernate (see Hibernate: Is it possible to store a transient field in a second level cache? ), So they should not be considered by ehcache anyway. Right?
source to share
It turns out the problem I am facing is a result of using Joda-Time instances in my model (I am using the Jadira UserType library to render Joda types).
Joda types contain all sorts of internal links (including links to chronological information leading to a huge object graph) and Ehcache is
looking at those links leading to my initial warning.
I haven't found a clean way of how to tune the SizeOfEngine engine to exclude these references, but then I figure a cleaner approach would be to force Hibernate to only put the relevant information into the second-level cache first (instance time in my case
Jadira made a poor choice when implementing its custom types: see my answer here
Here's what I found regarding my OP (using Hibernate 4.2.15.Final, EhCache 2.6.9 and UserType 3.2.0.GA):
First of all, I got a misconception about how Hibernate stores entities in it's second level cache. After reading Lorimer's blog post on Truly, understanding second-level caches and Query , many things made more sense to me:
- You don't need to worry about bidirectional associations (or circular graphs, for that matter) because Hibernate will only cache the identifiers for your associations. And even if it put a reference to the entire object in the cache, which is not, the EhCache SizeOf Engine would track the objects in the already visited graph and there will not be their size twice.
- Again, you don't need to worry about transient fields, because Hibernate won't cache them
- In theory, there shouldn't be any configuration problems
. Problems currently arise when you use custom user types that are incorrectly measured by the EhCache SizeOf engine.
source to share
I know this is an old question. But it might be helpful for someone. I have the same warning. I've spent a lot of time trying to solve this problem. In my case, EhCache does not ignore all hibernate proxy classes. My entity has lazy association fields and when measuring the size, EhCache looks at the entire hibernation graph.
Finally I found this page and solved it.
source to share