ColdFusion is a versatile, feature-rich platform for building web and mobile applications. Since version 6, ColdFusion has been powered by Java. This has opened up a wealth of resources for performance tuning and scaling ColdFusion to meet enterprise-grade demand. In this guide, we will introduce some foundational concepts of the Java Virtual Machine and how we can leverage its built-in capabilities to resolve bottlenecks in your ColdFusion application.
It is important to understand that performance tuning is a process, not a destination. Tuning your application for speed should be integrated into your broader maintenance strategy. We recommend integrating application performance tuning as part of your regular release pipeline testing. Small changes in your code can impact your application memory footprint and effect JVM performance.
Java Virtual Machine: The Beating Heart of ColdFusion
ColdFusion has been a Java-based server since version 6 (also known as MX). As with most Java applications, at its core is the Java Virtual Machine (or JVM). This is where your tuning effort will start. Just as a Formula One car cannot win races with a misfiring engine, if the JVM is not tuned adequately, nothing else in your application will work optimally.
Sun Microsystems created Java as a high-level programming language which should run on as many operating systems and hardware variations as possible. The goal of “write once, run anywhere” required a predictable, encapsulated operating system. The JVM is a multi-threaded environment abstracting the actual computer operating system from the application code. Adobe previously deployed its own JVM called JRUN, but switched to Tomcat in ColdFusion 10.
The default configuration of the JVM that ships with ColdFusion is intended to satisfy the broadest number of requirements. This is a good thing, as it means your application will work right out of the box. However, if you have not tuned your JVM to the needs of your particular application and infrastructure, there is a high likelihood you are running a sub-optimal configuration. Fortunately, the JVM ships with everything you need to begin inspecting the performance of your application.
First, It is important to understand some basic principles of how the JVM operates. The JVM segments its allocated memory into Generations.
Memory is subdivided into three Generations: Young, Old, and Permanent. In very general terms, think of the Young and Old Generations as containing your application code, and the Permanent Generation containing the classes needed to run the ColdFusion server. This is a slight simplification for the purposes of this guide. The actual distribution of memory is much more complicated.
When code is executed in ColdFusion, objects are created and reside in the Eden Space. There are two other spaces in the Young Generation: S0 and S1 (the Survivor Spaces). During the execution of requests, objects traverse between the Eden and Survivor spaces. This activity is monitored by a process known as the Garbage Collector (GC). Objects which are no longer referenced by any other objects are considered unused. The GC will attempt to collect (and release the associated memory) of those objects roughly 40-45 times while they are in the Young Generation. If the objects are not collected, they are moved to the Old Generation.
Why would the objects in the Young Generation not get collected? Usually, because there are persistent references to them in the application code. Shared scope variables (
server) are an example of objects that retain references for an extended period of time and wind up in the Old Generation. The more shared scope variables your application employs, the larger your Old Generation will grow. Objects that never release their references will become stuck in the Old Generation. This can cause memory usage to slowly grow over time and is commonly referred to as a memory leak.