Uploaded image for project: 'PUBLIC - Liferay Portal Community Edition'
  1. PUBLIC - Liferay Portal Community Edition
  2. LPS-60638

Improve CacheFilter hit rate for everything.jsp and barebone.jsp

    Details

      Description

      The filter chain is not very efficient for the everything.jsp and barebone.jsp. Effectively, the everything.jsp and barebone.jsp calls will always result in com.liferay.portal.servlet.filters.aggregate.AggregateFilter#getBundleContent method being called (&minifierType=js&minifierBundleId=javascript.barebone.files, etc.). In a stable environment without regular deployments that impact the JS scripts referenced, this effectively means that the result returned should always be from a cached file. So in effect you have a partially static resource that could be served by something like Apache Web Server front ends as mentioned in the "Liferay Portal Performance Best Practices" book.

      The com.liferay.portlet.servlet.filters.language.LanguageFilter then replaces key references in the combined everything and barebone JS files with language specific settings. This is done based on the "&languageId=en_AU" being one of the query string values. In our case, all users are set to have their default language as "en_AU". So in theory changes to the two combined JS files should be constant at this point as well.

      We then move on to the com.liferay.portal.servlet.filters.cache.CacheFilter#getCacheKey which constructs a rather elaborate key for the cache that includes the languageId (retrieved by a different method than the language filter), the full query string including the browser ID and the user agent with some other items. Taking a look at the sample values in our production access logs, this is going to make for a very inefficient cache for everything and barebone with so many UserAgent variations.

      I realise that this is a generic filter, but it may be far more efficient to have a simpler key for things like the everything and barebone JS resources which only effectively need the language. In a single language environment like ours, you would effectively end up being able to cache a single copy of each file. At the moment a lot more memory is used caching the everything and barebone JS files due to a copy per UserAgent effective.

      The above is slightly simplified as it ignores the compression etc. The general idea is that by removing things like the user agent from the key (at present neither of the JS files is agent dependent), you can increase the hit rate and decrease memory requirements.

      Making use of config parameters may allow the filter's key generation to remain generic and be configurable for specific cases. As an example, the UserAgent (or any of the other key components) could be included optionally.

      		// User agent
      
                      if (includeUserAgent) {
      		    String userAgent = GetterUtil.getString(
      			request.getHeader(HttpHeaders.USER_AGENT));
      
      		    sb.append(StringPool.POUND);
      		    sb.append(StringUtil.toLowerCase(userAgent).hashCode());
                      }
      

      A sensible default would then be provided for the includeUserAgent boolean option so that it only needs to be configured in the liferay-web.xml if not using the default.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              hong.zhao Hong Zhao
              Reporter:
              g.steyn Graeme Steyn
              Recent user:
              Csaba Turcsan
              Participants of an Issue:
              Votes:
              1 Vote for this issue
              Watchers:
              3 Start watching this issue

                Dates

                Created:
                Updated:

                  Packages

                  Version Package
                  7.0.0 DXP FP33
                  7.0.0 DXP SP7
                  7.0.5 CE GA6
                  7.0.X
                  Master