Accessibility

Table of Contents

Performance tuning for ColdFusion applications

Performance tuning with Java Virtual Machine parameters

Since ColdFusion is based on the J2EE platform, you can use JVM arguments to tune the performance of ColdFusion applications. ColdFusion 8.0.1 is shipped with Java Runtime Environment (JRE)1.6.

The Sun JVM supports several arguments that can be used to change basic behavior, tune performance, or change debugging settings. In this part I will discuss the performance tuning parameters provided by Sun Java SE 6. As examples, I will cover two applications built on ColdFusion, BlogCFC and Canvas Wiki, and provide recommendations on how to tune them using JVM arguments.

Sun Java memory management and definitions

In Sun Java, memory is managed in generations, or memory pools having objects of different size. There are different kinds of generations:

  • Young generation―This is the memory pool that holds objects with a high mortality rate. In ColdFusion this space holds variables that only exist on one page, such as those in the variable scope.
  • Tenured generation―This pool holds objects that live for a longer duration. In ColdFusion this space holds objects like Client and Session scope variables.
  • Permanent generation This pool holds persistent objects. In ColdFusion this space holds permanent objects like Application and Server scope variables.
  • Garbage collection (GC) refers to the process of recycling memory that was assigned to objects no longer referenced by a program:
  • Minor collection―Garbage collection that occurs in the young generation. In ColdFusion, minor collection will collect unreferenced local scope and variable scope variables.
  • Major collection―Garbage collection that occurs in the tenured generation. In ColdFusion, this will collect all unreferenced Session scope variables.

You can use the following arguments to tune memory management in Java:

  • -XmxDefines maximum Java heap size.
  • -Xms―Defines minimum Java heap size
  • -Xmn―Allocates space in the heap for the young generation.

The following terms are used in the discussion:

  • Pause time―When the garbage collector runs, it stops other process threads and the application appears unresponsive. This is called pause time.
  • Throughput―The percentage time not spent in garbage collection for a long duration of time.

For more details on generations, garbage collection, and arguments in Sun Java refer to the following resources:

Tools to measure performance

GCViewer is the open source tool that I used to obtain garbage collection profiles and measure performance metrics such as frequency of collections, pauses, heap size, and so on. For more details on GCViewer visit GCViewer.

I also used the freeware Apache JMeter software. This tool is used to measure end-to-end performance, including average response time and throughput. For more information refer to Apache JMeter. It is also used to simulate a load on the server.

Tuning the tenured generation

Figure 1 shows a garbage collection profile for BlogCFC with Xmx=1024m and 30 virtual users from JMeter running for 5 minutes. The purple area represents the tenured generation, yellow represents the young generation, and blue represents heap usage. The x-axis represents time and y-axis is a dual scale, shows JVM memory in KB and time taken by collector in seconds.

Garbage collection profile for BlogCFC

Figure 1. Garbage collection profile for BlogCFC

The profile in Figure 1 shows frequent major collections and frequent minor collections. Because major collections take more time, if you reduce the frequency of major collections then you can increase throughput. So if pause time is not an issue for your application, the following techniques will reduce the frequency of major collections:

  • Increase Xmx―This allocates more memory to the heap. If you have memory available, you can allocate it to the JVM and increase the overall size of the heap. This, in turn, will increase the size of the tenured generation, which will take more time to fill, hence reducing the frequency of major collections.
  • Increase Xms―This will increases the initial size of heap. If the initial size is small then the heap will have to resize itself frequently whenever the tenured generation is filled, which will lead to more major collections initially.

Collection profiles for Xmx=1024m,Xms=256m
(left) and                            Xmx=1024m,Xms=512m (right)

Figure 2. Collection profiles for Xmx=1024m,Xms=256m (left) and Xmx=1024m,Xms=512m (right)

As shown in Figure 2, doubling Xms decreases the frequency of major collections.

Throughput comparison for different values
of Xmx

Figure 3. Throughput comparison for different values of Xmx

Figure 3 shows the throughput improvement in the BlogCFC application when Xmx is increased from 1024MB to 2048MB.

Tuning the young generation

From a performance perspective, young generation collection is comparatively less expensive than tenured generation collection. Frequent young generation collection, however, can hamper performance. Also if collections are frequent then most objects remain alive making collection inefficient. When you decrease the frequency of young generation collection, then more objects will be dereferenced (or die) between two collections.

Collection profiles for Xmn=512m (left)
and Xmn=128m (right)

Figure 4. Collection profiles for Xmn=512m (left) and Xmn=128m (right)

The following parameters can be used for young generation tuning:

  • -Xmn―This parameter allocates space in heap for the young generation. If you have available memory, you can increase the –Xmn value to increase young generation size. This reduces the frequency of minor collections and gives short-lived objects in the young generation more time to die.

    On the other hand, if memory is limited then allotting more space to the young generation will reduce the space available for the tenured generation resulting in more frequent expensive major collections. As a first step, use memory profiling to analyze the usage of young and tenured generations. The profile in Figure 1 shows that the young generation is about 40% of the heap. In this case I would try allocating around 25-35% of heap to the young generation to see what percentage is optimal for the application.

    Figure 4 shows a decrease in frequency of minor collection with higher Xmn value. Figure 5 shows a throughput improvement for a higher Xmn value.

    Throughput comparison for different values
of Xmn

    Figure 5. Throughput comparison for different values of Xmn

  • SurvivorRatio―The SurvivorRatio parameter controls the size of the two survivor spaces in the young generation. For example: -XX:SurvivorRatio=8 sets the ratio between each survivor space and eden to be 1:8, each survivor space will be one tenth(as there are two survivor spaces) of the young generation.

    Decreasing the survivor ratio will increase the size of survivor spaces. Larger survivor spaces allow short-lived objects a longer time period to die in the young generation (see Figure 6). If your application has more objects that die young then tuning this argument will be more effective. To learn more about generations and spaces, visit Tuning Garbage Collection with the 1.4.2 Java Virtual Machine.

    Throughput comparison for different values
of SurvivorRatio

    Figure 6. Throughput comparison for different values of SurvivorRatio

  • TargetSurvivorRatio―The default value of TargetSurvivorRatio is 50. Increasing this (for example, by setting -XX:TargetSurvivorRatio=90) will allow better utilization of survivor space memory (see Figure 7).

    Throughput comparison for different values of TargetSurvivorRatiofor Canvaswiki Application.

    Figure 7. Throughput comparison for different values of TargetSurvivorRatiofor Canvaswiki Application.

Tuning with UseParallelOldGC

Prior to Java SE 6, young generation collection was done in parallel while major collections were performed using a single thread. In Java SE 6 major collections can be done in parallel with the new UseParallelOldGC setting. This garbage collection will be enabled by default in JDK6.

For JDK5 update 6 and later you can enable this feature by adding the option -XX:+UseParallelOldGC to the command line.

The results in Figure 8 show that BlogCFC performs better when using the UseParallelOldGC garbage collector. Applications that have frequent major collections typically benefit more from using the UseParallelOldGC setting.

Throughput comparison without -XX:+UseParallelOldGC and with

Figure 8. Throughput comparison without -XX:+UseParallelOldGC and with

Tuning with MaxPermSize

The permanent generation is used to hold class objects and method objects. So, if any application has lots of classes to be loaded and unloaded then increasing the size of permanent generation will reduce loading and unloading of classes and thus increase throughput. To increase the size of the permanent generation use the following command line option:

 -XX:MaxPermSize=<desired size>

Tuning with -XX:NewRatio

The NewRatio argument defines the ratio of the tenured generation to the young generation. The default value is 2, which means the tenured generation occupies 2/3 of the memory and the young generation occupies 1/3. By profiling your application you can tune this value to improve performance. For example, if the profile of the application shows the young generation occupancy as 20%, you can define –XX:NewRatio=4, so that the tenured generation occupies 4/5 of the memory and the young generation occupies 1/5.

There are more performance tuning options provided by the JVM, but I did not see a significant performance improvement using them in my environment. For more details on performance options, see Java HotSpot VM Options.