Finding that the use of @Fetch(FetchMode.SUBSELECT) results in a significant level of string duplication for SQL and SQL fragments. When loading large datasets and/or higher numbers of associations with multiple associations using SUBSELECT the memory can accumulate significantly (e.g. on the order of multiple GB for string space associated with the duplicate SQL fragments alone). The testcase has a rather small set of strings for only 600 simple entities.
An OQL query (in Eclipse MAT) like the below was used to obtain the strings/fragments related to queries when running in the debugger with a breakpoint at commit (e.g. in the attached test).
{noformat} select s.toString().length() as strlen, s.toString() from java.lang.String s where s != null and ( s.toString().contains("from Employee") or s.toString().contains("from Task") ) {noformat}
Then right clicking duplicated strings and using {{Merge Shortest Paths to GC Roots -> Exclude all phantom/weak/soft etc. references}} shows that the strings seem to be retained in a hierarchy like the below:
{noformat} class support.hibernate.entity.TestHibernate @ 0x82f29800 Native Stack '- entityManager org.hibernate.ejb.EntityManagerImpl @ 0xd9d931d8 '- session org.hibernate.internal.SessionImpl @ 0xd9d6e858 '- persistenceContext org.hibernate.engine.internal.StatefulPersistenceContext @ 0xd9e918e8 '- batchFetchQueue org.hibernate.engine.spi.BatchFetchQueue @ 0xd9f766d0 '- subselectsByEntityKey java.util.HashMap @ 0xd9f766f0 '- table java.util.HashMap$Entry[512] @ 0xd868c8d8 |- [91] java.util.HashMap$Entry @ 0xd8689588 | |- value org.hibernate.engine.spi.SubselectFetch @ 0xd8689540 | | '- queryString java.lang.String @ 0xd8689568 from Employee employee0_ ... {noformat}
In the attached test is a spreadsheet with some comparison for the string usage between SELECT and SUBSELECT fetch (see the Employee entity for the two associations). Note that the test is quite minimal in terms of usage, adding associations, etc. magnifies the duplication. |
|