I'm using ScrollableResults in Hibernate and iterating through millions of records. It's taking quite a bit of time, so I did some profiling with YourKit to try and figure out how we can make this iteration faster. I expected the time to be mostly spent in either fetching from Oracle, or hydrating objects... but to my surprise, it seems to be spending a large chunk of time calling System.identityHashCode.
Pertinent part of the profile:
There are 3 major things that seem to be taking time here:
T4CPreparedStatement.fetch- This is fetching from Oracle, about 13% of the time spent.AbstractEntityPersister.hydrate- This is creating the objects from theResultSet. Quite large, but I think I can mitigate a lot of this via other means. About 29% of the time.EntityEntryContext.addEntityEntry- This is where I have no clue how to improve because it's all spent inSystem.identityHashCode. It's 58% of the execution time.
I will note that this is quite an old version of Hibernate: 4.3.11, along with the elder JDK 8.
My ScrollableResults are being created this way:
CriteriaQuery query = ...;
ScrollableResults results = entityManager.createQuery(query)
.unwrap(Query.class)
.setReadOnly(true)
.setFetchSize(20000)
.setCacheable(false)
.scroll(ScrollMode.FORWARD_ONLY);
So, a couple questions:
- Is there a way to avoid
StatefulPersistenceContext.addEntityat all? We're not modifying any of these entities being returned, it's purely read-only, so I'm not sure why we need a persistent context... though I admit, my knowledge of the internals of Hibernate is severely lacking. - Is there a way to speed up
System.identityHashCode? The object has a lot of properties, mostly Strings and floats, but there are twoLocalDateproperties as well. Part of improving the object hydration will be changing fromLocalDatetoInteger... would that help? Unfortunately, YourKit isn't allowing me to drill further there (probably because it's anativemethod), so I've no idea.
Any insight is much appreciated!
