ColdFusion provides you many ways in which to cache various elements to improve performance. You have control of caching at various levels, from the caching of compiled ColdFusion Markup Language (CFML) templates to page- and query-level caching.
Understanding the types of caching available to you as a developer and the benefits and drawbacks of each is an integral part of learning how to draw the best performance out of your web applications.
Administrative Caching Options
The caching section of the ColdFusion Administrator is an appropriate place to start a discussion of caching. Figure 18.1 shows this part of the ColdFusion Administrator.
Figure 18.1. Caching section of the ColdFusion Administrator.
On this page of the ColdFusion Administrator, you see three options for configuring the way in which ColdFusion performs caching at an administrative level. We will look at each option in the following sections.
Template Cache Size
To understand the setting of the template cache size, it's important that you understand how CFML templates are processed after they're requested by a client's web browser. The process follows these steps:
The Template cache size (number of templates) text box in the ColdFusion Administrator enables you to predetermine the amount of memory that you want ColdFusion to use to store compiled CFML templates.
As an example of CFML template processing, let's say that I come to your site and request your index.cfm file. If this file has already been compiled, there's really no need for me, as a client, to force the ColdFusion Server to recompile this file just for me. If there's enough room in your template cache, ColdFusion looks in there for a compiled copy of the template, checks it against what's on disk to ensure that it is the latest copy, and then executes the template.
The preceding process saves ColdFusion several steps by not forcing a recompile of templates each time a new user requests them. This might sound simple, but it can have a profound impact on your overall server performance, especially on heavily trafficked sites. If your template cache is too small, it forces ColdFusion to go through many extra steps, which creates additional processing overhead.
Luckily, in the latest version of ColdFusion, Macromedia has made it very easy for you to determine the appropriate template cache size for your server. Simply take the total number of all the CFM files on your system, and enter that number into the Template cache size (number of templates) text box.
This approach is a slight departure from the way in which you would configure the template cache size in previous versions of ColdFusion. In older versions, after CFML files were run through the engine, they were compiled into P-code (pseudocode) that was slightly larger than the size of the original templates. Because of the larger sizes, Macromedia recommended that you set this setting to 3 5 times the total size of all your CFML templates to account for expansion.
In ColdFusion MX, changing this setting is not necessary because when templates are compiled, they are actually stored as bytecode (as .class files). This makes it much easier for you, as a developer, to properly make the configuration, because you will never need to cache more than the total number of templates that you have on a given server.
The next setting over which you have control is the Trusted cache check box. Often, this setting is overlooked or just left alone because the administrators of the server don't have a good understanding of what it does.
By checking the Trusted cache check box, you achieve another significant performance boost because you're taking another step to reduce the amount of work ColdFusion Server has to perform to answer a request.
When you check the Trusted cache check box, you are essentially telling ColdFusion that you are certain that none of the source CFML has changed; thus, whatever ColdFusion has already compiled in the template cache will be fine to use.
We've already discussed how ColdFusion responds to requests for CFML templates and the way in which the engine uses the template cache to check for existing copies of compiled versions of the code. Note that ColdFusion checks the template cache to see if there's already a copy of the compiled code in there and then checks the disk for a newer version of the code. If a newer version of the code doesn't exist on disk, ColdFusion uses the compiled copy in cache, thereby eliminating the need to recompile. This saves valuable overhead.
All that the Trusted cache check box does is tell ColdFusion to eliminate the disk check from that process. In other words, after a request is made for a template, ColdFusion Server checks the template cache for a compiled copy of the code. If it's there, ColdFusion executes that compiled copy rather than checking the disk to see if a newer copy of the source is available.
Understanding this process is key to understanding why using a trusted cache in production systems is a good idea. You are saving the ColdFusion Server valuable work by not forcing it to do a disk check each and every time it finds something in the template cache that it needs.
Of course, you must understand that if your code frequently changes, and if these changes need to be seen immediately after they are made, a trusted cache isn't likely the best choice for you. The general consensus is that to flush a trusted cache, you'll need to restart the ColdFusion Server. Although this isn't technically true, the only way to flush the cache (short of a restart) is through the use of undocumented functions that might (or might not) be supported in future releases of ColdFusion.
Of course, this shouldn't be a problem on production servers where code changes occur very infrequently. If your organization already has a change cycle in place, it's usually easy to add a flush of the trusted cache to the steps involved in moving new code to production.
One of the common misconceptions I've heard about the use of a trusted cache is that developers fear that if they have dynamic content in a template, such as the results of a query, that content will be the same for all users who get a copy of the template from the trusted cache. This is simply not true. You can use a trusted cache confidently, regardless of the amount of dynamic content contained in a particular template's output. Only the compiled template is cached; it still gets executed (or run through the server) on each request so that content can be customized on a per-user basis.
Limit Maximum Number of Cached Queries
The final option that we're presented with in the caching section of the ColdFusion Administrator has to do with limiting the maximum number of cached queries that we want ColdFusion to store in random-access memory (RAM) at any given point.
By default, this option is set to 100; but contrary to what you might have heard in the past, there is no maximum limit. You can in fact choose to store as many queries in memory as you have free RAM available. Of course, you need to be aware of the size of your result sets when setting your maximum cached query value to make sure that you don't overload your free memory. Obviously, if your result sets are very large, the application memory footprint reflects this if you're storing a large number of cached queries.
With regard to the cached queries resident on the server, one of the more common complaints has been the impression that you need to restart the ColdFusion Server to clear queries out of cache. In reality, you can effectively flush the cached queries by using the following code:
Running this line of code clears the entire query cache. Thus, new result sets can be stored in place of the old ones.
Summary of Administrative Caching Settings
As we've outlined, the ColdFusion Administrator provides us with three areas in which we can improve system performance by implementing caching. We're presented with a way to adjust the template cache, we're permitted to switch Trusted cache on and off, and we can specify the maximum number of cached queries that we want to store in server memory at any given time. Table 18.1 examines the benefits and drawbacks of using these options.
Query caching is an effective way to increase application performance by reducing the number of trips that ColdFusion must make to the database. When you have a query that is cached, the result set is read from server memory and immediately delivered to the user, without the need for an actual connection and data retrieval process.
One of the first steps you need to do as a developer when deciding to utilize query caching is to make intelligent decisions about the specific queries that you want to cache.
The example most commonly used when discussing query caching is one in which you are retrieving a list of U.S. states from a database to fill a drop-down list on a form. Because you're relatively certain that a new state isn't going to be added to the union in the next few days, you can feel comfortable caching this query. You know beforehand that the data returned by the query is unlikely to change from user to user, so there's no doubt that this is a good candidate for query caching.
The preceding paragraph contains a pretty good example of the types of queries it makes sense to cache, but it doesn't go quite far enough. Even if the data returned by a specific query changes hourly, you can still get a nice performance boost by caching this query as well. As a matter of fact, about the only time you really shouldn't use query caching is when the result sets will be different each and every time, for each and every user.
To cache a query, you just need to put the cachedWithin or cachedAfter parameters within the query syntax. As an example, let's assume that I want to query a database to get a list of all valid users of my web application. With no caching at all, my query might look something like this:
<cfquery name="qGetUsers" datasource="#request.datasource#"> SELECT * FROM tbl_Users </cfquery>
This is a very simple example based on a basic query. I'm sure you've done something similar in your application development.
Now let's assume that I want to cache this particular query, and I want it to remain cached for the next 3 hours. Thus, every additional user who comes to my site within the next 3 hours to retrieve this same data will be able to do so without ever having to make a trip to the database. The code would look like the following:
<cfquery name="qGetUsers" datasource="#request.datasource#" cachedWithin="#CreateTimeSpan(0,3,0,0)#> SELECT * FROM tbl_Users </cfquery>
As you can see by the example, I've added the cachedWithin attribute to my CFQUERY syntax, and I've used the CreateTimeSpan function to tell ColdFusion that I'd like to have this query cached for the next 3 hours.
When using the cachedWithin attribute of the CFQUERY tag, the cached query data is used to answer all requests that come in during the time span specified. A time span is specified to the cachedWithin attribute through use of the CreateTimeSpan function.
Now let's assume that this is a production server, and I know that I'll be doing a database update on April 26, 2002. Prior to that time, I don't want the query to be cached, but for every request that comes in after that date and time, I would like the cached query results to be used.
This can be achieved easily by using the cachedAfter attribute of the CFQUERY tag, as outlined in the following example:
<cfquery name="qGetUsers" datasource="#request.datasource# cachedAfter="April 26, 2002"> SELECT * FROM tbl_Users </cfquery>
When using the cachedAfter attribute of CFQUERY, you can pass in a date/time value after which you want the cached result set to be used. If a request is made for that particular query prior to the date/time value you've specified in the cachedAfter attribute, the query is run as if it were not cached at all.
It should be noted that for a cached query to be retrieved from RAM, the calling template must have the exact same structured query language (SQL) string as the query in cache. Otherwise, the query will be rerun with the new SQL string, and a new copy will be cached.
In addition to compiled code and queries, there are times when you might want to cache the actual Hypertext Markup Language (HTML) output produced by a particular CFML template. With the CFCACHE tag, you can do just that.
The CFCACHE tag enables you to dramatically speed up the rendering of pages that won't contain dynamic, customized content for each user. When you use CFCACHE within a CFML template, ColdFusion renders a temporary file that contains the HTML output that the execution of the cached template produced.
Although you can't use CFCACHE for templates that change frequently, you can get away with using CFCACHE for templates in which the only changes are in the uniform resource locator (URL) parameters that are passed in.
For example, let's assume I have a page called doSomething.cfm. Based on the URL parameter that is passed in as a URL action, either an add, edit, or delete form is displayed.
To call the doSomething.cfm file when I want to edit the form, I might call it like this:
Fortunately, I'm still able to use CFCACHE with this page because of the way in which the CFCACHE tag works.
In addition to creating temporary files containing the HTML content of the cached files, CFCACHE also creates a cache mapping file (cfcache.map). It enables me to have different copies of the cached content based on the URL parameters that I will be passing in.
To continue with the previous example, my cfcache.map file might look something like this:
[doSomething.cfm] Mapping = C:\WebRoot\CF01.tmp SourceTimeStamp = 04/26/2002 06:52:04 AM [doSomething.cfm?Action = "Edit"] Mapping = C:\WebRoot\CF02.tmp SourceTimeStamp = 04/26/2002 12:42:17 AM [doSomething.cfm?Action = "Add"] Mapping = C:\WebRoot\CF03.tmp SourceTimeStamp = 04/26/2002 04:23:09 AM [doSomething.cfm?Action = "Delete"] Mapping = C:\WebRoot\CF04.tmp SourceTimeStamp = 04/26/2002 11:22:19 AM
The ColdFusion Server will use the SourceTimeStamp value located in this map file to make sure that it's using the most up-to-date copy of the source template to produce the cached results.
Invoking CFCACHE within a particular CFML template is an easy thing to do, and it is often as simple as invoking CFCACHE at the top of the template in which you want caching to occur.
For a full view of the attributes you can use with CFCACHE to gain more control over how templates are cached, refer to Appendix A, "Tag Reference."
Other Caching Methods
In addition to the caching methods that are provided for you internally by the ColdFusion Server, there are also a multitude of CFML-based custom tags that take the concept of page-based caching even further. One of the better custom tags for page-based caching is the CF_SuperCache tag that was developed by various members of the former Allaire Consulting Services team.
Using this paired custom tag, you can specify specific portions of a template that you'd like to have cached to RAM or disk. This is an alternative to caching for an entire page or not at all.
The CF_SuperCache tag is included at the official web site for this book, which is www.insidecoldfusionmx.com. In addition to this tag, you'll want to check the Macromedia Developer's Exchange at http://devex.macromedia.com/developer/gallery/, where you can find many other custom tags that address your caching needs.