Показаны сообщения с ярлыком cache. Показать все сообщения
Показаны сообщения с ярлыком cache. Показать все сообщения

среда, 26 января 2011 г.

Speedup unspeedable

    A few days ago i have got some well know e-commerce platform to speed up it. Application use hibernate, solr, spring and spring mvc with apache velocity as view and look like very over optimised, cached everything, that possible. It cached solr results, hibernate use second level cache, web tier use etag, etc. I was frustrated, because no easy way to boost performance. After several hours of investigation some bright idea came to me - if solution cache the result of named query, why not cache the result of page rendering for most very popular pages product and category views ? Of cause not all pages can be cached !
   To achive good result need to hack the VelocityLayoutView. Create a derived class put rendering result into cache. Solution became two times faster. Guess not a bad result.


   1:  public class DerivedVelocityLayoutView extends VelocityLayoutView {
   2:   
   3:  // skipped
   4:   
   5:      private oncurrentMap<String, String> cache;
   6:   
   7:  // skipped
   8:   
   9:      /**
  10:       * Default constructor.
  11:       */
  12:      public DerivedVelocityLayoutView() {
  13:          super();
  14:          this.requestHelper = new RequestHelperImpl();
  15:          this.cache = new MapMaker()
  16:              .concurrencyLevel(16)
  17:              .softValues()
  18:              .expiration(3, TimeUnit.MINUTES)
  19:              .makeMap();
  20:      }
  21:   
  22:  // skipped
  23:   
  24:  /**
  25:       * The resulting context contains any mappings from render, plus screen content.
  26:       * @param velocityContext context.
  27:       * @throws Exception in case of exception
  28:       */
  29:      private void renderScreenContent(final Context velocityContext) throws Exception {
  30:   
  31:          if (logger.isDebugEnabled()) {
  32:              logger.debug("Rendering screen content template [" + getUrl() + "]");
  33:          }
  34:   
  35:          final HttpServletRequest servletRequest = (HttpServletRequest) velocityContext.get("request");
  36:          final String key = getKey(velocityContext);
  37:   
  38:          String renderedPage = cache.get(key);
  39:          if (renderedPage == null) {
  40:              StringWriter sw = new StringWriter();
  41:              Template screenContentTemplate = getTemplate(getUrl());
  42:              screenContentTemplate.merge(velocityContext, sw);
  43:              renderedPage = sw.toString();
  44:              if (isCacheAllowed(servletRequest.getRequestURI())) {
  45:                  cache.put(key, renderedPage);
  46:                  if (logger.isDebugEnabled()) {
  47:                      logger.debug("Cache miss  " + key);
  48:                  }
  49:              }
  50:          } else {
  51:              if (logger.isDebugEnabled()) {
  52:                  logger.debug("Cache hit   " + key);
  53:              }
  54:          }
  55:          // Put rendered content into Velocity context.
  56:          velocityContext.put(this.screenContentKey, renderedPage);
  57:      }
  58:   
  59:  // skipped
  60:   
  61:  }
  62:   

пятница, 5 марта 2010 г.

Second level cache in hibernate

Do you use hibernate ? I guess - yes, if you are here.
Do you use second level cache and query cache with hibernate? Are you happy with performance? I dont know... probably. Actually I am not happy with hibernate performance with query cache and 2nd level cache. Lets look inside ;)
First of all you have to understand, that 2nd level cache used when you perform lookup entity by id. Sound good, but by default entity will be cache without collections. The first solution - enable cache for collection in configurations, it will works for bags, lists, collections, sets, maps.
Second - query cache. It cache only the ids and must be used in conjunction second level cache.
Everything not bad at surface, but when you create hibernate and ehcache configuration and run you solution you will be surprised. Hibernate still hit you db :( Root cause - collection cache will not works for map, that has a map-key, and you db will be hitted a lot of times per single entity.
How to solve this ? Throw away the hibernate cache and use cache aspect in your application, it save a lot of you times, IO operations and CPU. It more predictable way that hibernate cache and allow to cache that you really need :)