I enjoy keeping up with the ColdFusion Podcast whenever I can, but I usually lag behind by a couple weeks until I find the time to listen to a few of them during some downtime. This morning I began listening to the most recent podcast at home, and then continued during my drive to work. The podcast was so interesting that I found that I had to share my right hand between the manual shifter and a notepad where I was jotting down some thoughts regarding Episode 21, Performance Tuning ColdFusion MX Applications.

Here I'd just like to take a moment to annotate some of the bullet points from the discussion while also extending with additional information.

Improve applications with better SQL statements
Optimizing queries can be the most significant factor to improve any ColdFusion application. Design the database well from the beginning and let the database do the work by through advanced SQL, thus reducing the need for less efficient post-processing and filtering of data in ColdFusion applications.

The podcast goes on at length about this topic including additional database and programmatic techniques to make applications faster.


Break application view into smaller parts for faster loading
An example: Users are more likely to tolerate several brief page loads with 10 form fields than one long page load with 50 form fields.


Fine optimization of CFML language constructs
Is StructKeyExists() faster than IsDefined(), and does it matter? The answer is it probably doesn't matter. Squeezing 50 milliseconds here and there pales in its impact compared to writing better queries that runs faster while reducing post-processing in ColdFusion.

In other words, there are probably several pieces of low hanging fruit that can be tackled first. Don't worry about fine optimization of language constructs until you've tackled the glaring bottlenecks first.


Exercising Language Constructs vs Load Testing
Does comparing 10,000 iterations of structKeyExists to 10,000 iterations of isDefined() help make your applications faster? Maybe. Does it really apply to the real world? Probably not.

Its more applicable to emulate real world conditions by load testing the application as it is written using tools such as the free Microsoft Web Application Stress Tool or the professional grade Segue Silk Performer.

There may be runtime anomalies that only appear under complex circumstances during load, such as with testing the application in a multithreaded manner with numerous virtual users. You could program a load test to run a typical path through the application to emulate a filling a shopping cart and performing a checkout, and combine that with a mixture of heterogeneous requests to emulate other users just clicking around.


RAM is cheap, use it
Identify queries that are good candidates for caching. Queries can be cached using the built-in cachedwithin attribute or you can store them in the application scope. The default cached query setting is 100, which truly an arbitrary number since that could be 100 queries of 1 row each or 100 queries of a million rows.

While RAM is cheap and you could keep caching queries to your heart's content, you'll understand the application better by knowing which queries are being cached and their approximate record count. That information could be used to calculate an estimate for query memory requirements. The default of 100 can be increased, but be very conscientious of the memory requirements when doing so. Otherwise, the limit is a queue (FIFO or maybe a LRU), so once the max has been reached, to add a new query to the cache the oldest or the last recently used query is bumped out.


Timeout Requests
While the podcast does recommend enabling this general setting, they omit the known limitation that requests that are waiting on database result will not timeout during that wait, even if it greatly exceeds the server or page-level timeout period. More on that here.


Trusted Cache / Template Cache
It's recommended to turn on Trusted Cache in the CF Admin. The Trusted Cache setting says to trust the pages already in the Template Cache and to stop checking the timestamps on the source cfml files. Changes to source files will not be reflected, with 2 exceptions. As noted in the podcast, if the ColdFusion server is restarted, the changed source files will be detected and the updated page will be used.

Take note, however, that (omitted in the podcast) beginning in ColdFusion MX 7 there is a button on the bottom of the CFAdmin Caching page for "Clear Template Cache Now" (sic imperative). If Trusted cache is on and a file that has already been compiled and cached has had its source file updated, rather than restart the ColdFusion server (which will terminate user sessions), you can just click the button for clearing the template cache. The cached version of the template will be updated, and if you were saving class files to disk that will be updated too. Finally, there is also a programmatic way to clear the template cache using the Admin API.


Use AJAX for better user experience
While the podcast recommendation is to use AJAX, the technique is equally effective using other RIA techniques such as Flash Remoting or Flex. These technologies improve performance by loading the initial page view and then updating that view with asynchronous calls to the server where only small bits of data are exchanged rather than having to refresh or repaint the view.

In other words, the browser doesn't have to make new requests for graphics or other display code multiple times. For example, when a user fills out a form by entering an address, the user could be prompted to input the zip code and an AJAX or FR call could obtain the city and state and pre-fill those fields.


Performance Monitoring
The podcast makes a brief suggestion to use NT Performance monitor, Fusion Reactor, or See-Fusion to introspect the state of the ColdFusion server such as number of requests running, requests queued, average db times, etc.

Don't forget that on Server Configuration you have at your disposal the cfstat utility which can output a limited set of information on the console. The cfstat data is programmatically accessible through the function getMetricData(). For Multiserver configuration with JRun, the JRun Metrics provide a rough equivalent. SeeFusion and Fusion Reactor, of course, provide significantly more information than any current built-in utilities.


Turn off Debugging Setting in Production
This has historically been known as a performance drain on production servers, so unless it is specifically needed in production for a short time, turn the general Debugging setting off. Brian Kotek and Brian Rinaldi recently had some interesting comments regarding this.




Some topics not discussed in this podcast:

Simultaneous Requests
Arguably, this is the most important setting on the ColdFusion server. Read here to understand why.


How to Troubleshoot Server Unresponsiveness
Here's part 1 and part 2 of my recommendations for where to begin when attempting to diagnose a problematic ColdFusion server. Since this is such a common topic for me, here is yet another blog post about diagnosing slow servers and the bottlenecks we love to hate.


Save Class Files
With ColdFusion MX 6.0, the inaugural J2EE incarnation of ColdFusion, cfml source files began to be compiled to Java source and then to Java bytecode via the Jikes compiler. This compiler was noticeably slow, which made the initial page compile very painful. In ColdFusion MX 6.1 a new and much faster compiler was added, and in ColdFusion MX 7 an option was added to not save the corresponding class files at all. The latter is a setting on the Caching page of the CFAdmin. The new compiler is so fast that you might as well not even bother saving class files, so uncheck that setting and save some disk space. More about this.


CMS Apps may have their own considerations
Content Management Software may have special considerations for performance tuning. In fact, the ColdFusion knowledge base has a technote just for the Commonspot CMS from Paperthin.


Additional topics to be blogged about at another time include mail server thread pool settings, database connection pool settings, and file upload throttle settings.