I recently came across a unique issue with a client. I was working on some performance optimizations due to latency on page load. I found an interesting issue around caching and this inspired my blog. Without giving any specific details, the client had developed an enhancement which allowed them to lookup custom data associated to any object within Liferay. This custom data is retrieved by the company ID, resource name, and resource primary key.
In this scenario, there is a very heavily used feature which retrieves this custom data to make decisions. On every page load, we’re making multiple lookups. It is likely the most used feature within the site. In my research I found that custom data was only used on a small number of the objects in Liferay. In most cases, the method was performing a database lookup and not finding any results. It would return a null response and that was acceptable.
Here’s the gotcha. The Liferay Service Builder code will cache the data retrieved from Hibernate only when the data exists. If no records are found, then nothing will get cached. Therefore, this particular feature was bypassing any caching optimizations. On every page load, we were performing multiple database queries with the same result (no records found). This additional database activity was causing a delay on page load.
Without redesigning the entire feature I easily inserted a caching utility. This utility was designed using the Liferay Multi-VM cache pool. New cache configurations were setup with the appropriate TTL, TTI, and sizing to ensure we don’t affect JVM GC. It will simply perform the Service Builder lookup, aggregate the results as needed, and cache them. The important distinction is that it also cached an empty list when no results were found in the database. This eliminated all the unnecessary database activity resulting from continually looking for records that do not exist.
I welcome your comments and suggestions. I’m sure there’s plenty of other ways to tackle this issue.