In Part 1 of this series, I talked about what caching is and why you would want to consider it as part of your application design. In this post, I'm going to spend some time talking about caching granularity. Caching granularity is just a fancy way of saying "what to cache". Before we go further, let's take a look at various caching opportunities you have when architecting an application:

As you can see, there are quite a few places where you can implement caching. For the purposes of our discussion, we're going to focus only on caching at the ColdFusion application server level. We'll take a look at what you can cache within your applications as well as the pros and cons associated with each item. There are 5 basic items to consider for caching at the application server level:

Data - Most ColdFusion developers have cached data at some point or another. In it's simplest form, caching data is nothing more than taking a simple value like a username or some other data type such as a structure or list and sticking it in a shared scope variable in the application, session, client or server scope.

Pros

  • Easy to implement
  • Easy to invalidate individual data elements

Cons

  • Most data still needs to be manipulated before it can be rendered - especially values stored in lists, arrays and structs.

Query Result Sets - Another popular technique familiar to ColdFusion developers is query caching. I don't think I know a ColdFusion developer who doesn't make regular use of this feature. This was one of the earliest caching enhancements made to ColdFusion and it's dead simple to implement. In fact, it's as simple as simple as adding one of two possible attributes to the cfquery tag (cachedwithin or cachedafter). Here's an example that caches query results for 60 minutes:


<cfquery
name="getUsers"
datasource="myPeeps"
cachedwithin="#createTimeSpan(0,0,60,0)#">

select userID
from users
</cfquery>

Pros

  • Simple to implement
  • Will provide performance gain in many cases
  • ColdFusion 8 added support for cfstoredproc and cfqueryparam

Cons

  • No visibility into the cache
  • Difficult to invalidate single cached queries
  • Clearing the entire query cache does it for the entire server
  • Recordsets still need to be processed before being displayed. This can have serious consequences for CPU and memory.
  • Storage of an entire recordset when only partial data will be used
  • Cache miss results in re-execution of the query. Can lead to the "dog-pile effect", which we'll cover in a later post.

It's also possible to cache query results in ColdFusion by assigning the result set of a cfquery operation to a shared scope variable such as a session or application variable. There are also additional pros and cons to using this method:

Pros

  • Allows for more granular control over cached items

Cons

  • Requires programmatic cache management

Objects - Objects in ColdFusion can refer to native CFC based objects or those instantiated through other technologies such as COM, CORBA and Java. Until ColdFusion 9, the only way to natively cache an object in ColdFusion was to place it in a shared scope variable such as an application or session variable. We'll talk about how this changes in ColdFusion 9 in a later post. For now, consider the pros and cons of caching objects.

Pros

  • Objects can represent complex relationships that may be impossible or at the least very expensive to compute at the data tier

Cons

  • Objects may need to be serialized/deserialized depending on the caching mechanism being used.
  • Requires programmatic cache management

Partial Page Content (Fragments) - Caching partial page content is something that's always been possible in ColdFusion but has never been elegant - until ColdFusion 9. Prior to version 9, you could cache part of a page by using the cfsavecontent tag and caching the enclosed content in a shared scope variable such as an application or session variable. There are also several custom tag based solutions that achieved the same thing (always storing in a shared scope variable).

Pros

  • Allows you to cache sections or fragments of content
  • Multiple cached fragments can be used within a single page.
  • Works well in situations where pages are made up of customized content, but the content itself is not necessarily unique

Cons

  • Requires programmatic cache management

Entire Web Pages - The final type of content to consider caching is the entire web page generated by ColdFusion. In terms of pure performance, this is the most desirable item to cache. Realistically, though, it's often impossible to cache entire web pages because of the amount of dynamic content on a a page, or because the page is updated too frequently. Caching entire ColdFusion generated pages goes back pretty far in the language history and has been supported via the cfcache tag. The main issue in versions of ColdFusion prior to ColdFusion 9 has been that the cfcache tag has always cached full pages to disk for server side caching. While this would be ok for static files served up by your web server, disk based caches are relatively slow for application servers when compared to RAM based caches. A secondary issue with cfcache pre-ColdFusion 9 is that there was not fine grained control over the cache making cache management difficult at best. All that changes in ColdFusion 9, of course.

Pros

  • Provides for the fastest performance

Cons

  • Won't work for pages with lots of customized content (see partial page caching)
  • May be problematic if the page content is updated too frequently

Now that we've discussed what you can cache, here are a few additional tips worth considering:

Cache as close to the final state as possible

  • E.g. don't cache a recordset if you'll ultimately use it to build a dropdown box
  • Cache entire pages whenever possible

Cache to static files whenever possible and let your web server serve the files

  • Works well for content that rarely changes
  • For dynamic sites, look to other options

Be mindful of cache size

  • May limit what/how much you can cache

I hope this has given you a good overview of the types of things that can be cached in ColdFusion. The next post in this series will introduce caching architectures.

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
Shawn Holmes's Gravatar All ColdFusion programmers, regardless of what skill level they 'think' they are, need to read and absorb all of these articles on caching.

And then, implement.
# Posted By Shawn Holmes | 7/30/09 10:57 AM
Mike Brunt's Gravatar Nice article Rob; and Shawn, yes you are right on in my opinion. At a recent conference, O'Reilly Velocity in San Jose, I began to realize how totally crucial caching is as we continually expand usage of the web by constructs like FaceBook, Twitter, MySpace and Google. One issue we face in CF and other similar server paradigms is effectively managing caches, it is a great challenge. Also we should try to reduce the number of requests actually getting to the web server and then CF and the Database, this is doable. Also, calling out to third party sites, such as affiliates can cause very significant performance issues, we should look at caching those items too, again this is doable.
# Posted By Mike Brunt | 8/22/09 3:41 PM
David McGuigan's Gravatar Rob! Great article. Can't wait for the rest of the series.

Manually implementing my cache control and management through exclusive use of the server and application scopes has always felt plenty elegant to me, but I'm ecstatic for all of the new options and had never thought about it from the perspective you suggest. Caching as a default redux in serverware workload as opposed to as a strategic performance enhancer for expensive activities. I love it.
# Posted By David McGuigan | 9/1/09 12:53 AM



Copyright 1995-2010 Rob Brooks-Bilson. All rights reserved.
Aura skin for Raymond Camden's BlogCFC inspired by Joe Rinehart & Steven Erat. This blog is running version 5.9.004.