Make Your Solution Faster

A couple of months ago I announced a new Glass.Mapper.Sc feature called Cache Always On. This feature has now been released in version 5.4.18 of Glass.Mapper.Sc and I wanted to dive into what this change means and how it works.

Beta Feature

This feature is beta and we are looking for feedback. If you do enable cache always on please let us know about your experience.

Enabling Cache Always On

By default Cache Always On is disabled and needs to be enabled in the Glass config as shown below:

  public static  class GlassMapperScCustom
  {
		public static IDependencyResolver CreateResolver(){
			var config = new Glass.Mapper.Sc.Config();

            config.Cache.AlwaysOn = true;

			var dependencyResolver = new DependencyResolver(config);
			// add any changes to the standard resolver here
			return dependencyResolver;
		}

Once enabled this changes the tasks that are added to the object construction pipeline, swapping the SitecoreCacheCheckTask for the SitecoreCacheAlwaysOnCheckTask (exciting stuff!).

The Cache Is Always On

Enabling cache always on causes a major change in the way that models are generated. As the name suggests the cache is now considered "on" for all models. So for example the following two requests for a model will both return the same cached instance:

    var item1 = service.GetItem<MyModel>(path, x => x.CacheEnabled());
    var item2 = service.GetItem<MyModel>(path);

The cache can be explicitly avoided by setting the disabled flag:

    var item1 = service.GetItem<MyModel>(path, x => x.CacheDisabled());

Memory and Caching

Since the cache is always enabled you will need to consider the memory usage of your models. If you have a large solution with a huge number of pages then the cache could become very large very quickly and cause memory pressures on your machine. If you enable cache always on you should monitor the memory consumption on your servers.

Due to the way that the objects are added to the cache and the fact that each objects may have multiple references from other objects it isn't possible to evict single objects from the cache to reduce the amount of memory usage. Setting memory thresholds or expiration times may not actually remove an object from memory because other objects in the cache may have references to the object which will keep it alive. The only way to reduce the memory consumption is to completely clear the cache.

The cache itself is completely cleared after a Sitcore publish like the Sitecore HTML cache.

Cache Always on also uses lazy loading and therefore proxy objects. This means that these cached objects can't be easily serialised for remote storage or transmission, therefore you will need to use a cache that stores the models in the servers memory and not in a remote shared cache, e.g. REDIS or similar.

Lazy Loading

Cache always on takes advantages of the changes we made in V5 which allows the framework to support caching and lazy loading. You can now cache large object graphs but without the whole graph being loaded on the first request.

This delayed loading of data into the cache should mean an increase in page first load performance and more flexibility for developers.

To perform lazy loading Glass keeps the underlying ISitecoreService used to load the model alive as part of the proxy object. This means that the ISitecoreService lifecycle will live for an indeterminate amount of time and shouldn't be disposed by a IOC container to earlier.

IOC

As stated above the underlying ISitecoreService will now live for a indeterminate amount of time, therefore you should not register the ISitecoreService as having a per-request or scoped lifecycle.

The ISitecoreService is a 1-1 wrapper for the underlying Sitecore Database and the Sitecore Database object itself is a singleton. It is therefore probably safe to register the ISitecoreService as a singleton itself. IOC registration is discussed in more detail as part of the Glass.Mapper.Sc training course.

SitecoreContext

Cache Always on will not work with the class Glass.Mapper.Sc.SitecoreContext, if you enable this feature and use SitecoreContext you will receive an exception. You should replace the SitecoreContext class with one of the appropriate alternatives like MvcContext/RequestContext/WebFormsContext.

Feedback

If you give Cache Always On please let us know how you get on. We are excited by this feature and look forward to hearing how it is used.

- Mike

Glass needs your support!

Glass.Mappper.Sc is supported by the generous donations of the Glass.Mapper.Sc community! Their donations help fund the time, effort and hosting for the project.

These supporters are AMAZING and a huge thank you to all of you. You can find our list of supporters on the Rockstars page.

If you use Glass.Mapper.Sc and find it useful please consider supporting the project. Not only will you help the project but you could also get a discount on the Glass.Mapper.Sc training and join the Rockstars page.

Become a Rockstar