[JIRA] (HHH-16726) Relax readability condition for strict read-write cache items.
by Guenther Demetz (JIRA)
Guenther Demetz ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... ) *created* an issue
Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiM2ViNDA1OTlm... ) / Improvement ( https://hibernate.atlassian.net/browse/HHH-16726?atlOrigin=eyJpIjoiM2ViND... ) HHH-16726 ( https://hibernate.atlassian.net/browse/HHH-16726?atlOrigin=eyJpIjoiM2ViND... ) Relax readability condition for strict read-write cache items. ( https://hibernate.atlassian.net/browse/HHH-16726?atlOrigin=eyJpIjoiM2ViND... )
Issue Type: Improvement Affects Versions: 5.6.15, 6.2.3 Assignee: Unassigned Components: hibernate-ehcache, hibernate-jcache Created: 31/May/2023 05:02 AM Environment: Hibernate 5.6, 6.2, Java 17, Windows 11, SQLServer Labels: CacheConcurrencyStrategy.READ_WRITE Priority: Minor Reporter: Guenther Demetz ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... ) Original estimate: 0.33h Remaining Estimate: 0.33h
Doing some heavy load-tests using Locust we discovered that performance goes down when multiple threads are filling 2ndLevel cache simultaneously with the same persistent objects.
Although all threads have more or less the same transaction start timestamp, when it comes to checking the readability of a read-write cache item, the current logic makes following comparison:
public boolean isReadable(long txTimestamp) {
return txTimestamp > timestamp;
}
This implementation considers items unReadable also when the timestamp of current transaction *equals* to the timestamp of the cached item.
My proposal is to change the condition to
{{ return txTimestamp >= timestamp;}}
so that a transaction which started simultaneously with the one that cached the item, can consider valid the puts of other transactions of same age.
This has to be modified in:
Hibernate 5.6:
class org.hibernate.cache.spi.support.AbstractReadWriteAccess.java
Hibernate 6:
classes org.hibernate.cache.ehcache.internal.strategy.AbstractReadWriteEhcacheAccessStrategy.java & org.hibernate.testing.cache.AbstractReadWriteAccessStrategy.java)
By overriding the used region factory the user can choose which granularity he wants for the timestamp comparison, for instance in our use-case we don’t want to go beyond fractions of seconds.
public class MyJCacheRegionFactory extends JCacheRegionFactory {
// UNIT SECONDS
public long nextTimestamp() {
return System.currentTimeMillis() / 1000;
}
...
}
Applying these 2 tweaks on hibernate5.6.15 I was able to enhance the performance in remarkable way:
100 threads accessing fresh (empty 2ndLevelCache) persistence at same time.
With
<property name="hibernate.cache.region.factory_class" value="JCacheRegionFactory"/>
Threads ran for 14.231 ms with over 247.000 isReadable calls returning false.
<property name="hibernate.cache.region.factory_class" value="MyJCacheRegionFactory"/>
Threads ran for 7.365 ms with 0 isReadable calls returning false.
( https://hibernate.atlassian.net/browse/HHH-16726#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-16726#add-comment?atlOrigin=ey... )
Get Jira notifications on your phone! Download the Jira Cloud app for Android ( https://play.google.com/store/apps/details?id=com.atlassian.android.jira.... ) or iOS ( https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=EmailN... ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100225- sha1:a994ca2 )