I have been trying to improve the speed of a ColdFusion application. It was written by a part-timer, a Java developer who was new to ColdFusion. He wrote the code almost entirely in cfscript, and he used CFC objects extensively. In fact, it seems that he overused CFC objects—to the point where the server slows to a crawl.
The application is a room reservation tool. The interface displays a table/grid of rooms and their availability throughout the day. The grid is a object, each room within the grid is an object, and each reservation within the room is an object. With 20 rooms and up to 4 reservations per room, there were easily up to 81 complex objects instantiated per page load. During testing, the pages often took 5-10 seconds to load. Under load, the pages took minutes to load. Memory use skyrocketed, and I had to run garbage collection manually via the ColdFusion server monitor to get it to respond to further requests.
I found Robert Munn’s series of blog posts:
- Object instantiation and heap size in ColdFusion
- Object instantiation and heap size in ColdFusion – Part II
- Object instantiation and heap size in ColdFusion – Part III
- Object instantiation and heap size in ColdFusion – Part IV
His observations are very similar to mine (although the decline in server performance, in my experience, was far more drastic).
I haven’t yet addressed the all the issues in the room reservation application, but as a proof-of-concept I re-created the interface using a single object—a ColdFusion query object—rather than the original hierarchy of objects-within-objects-within-objects. The new page loaded 10 times faster than the original.
I was concerned that I hadn’t really found the problem, though. My new code was circumventing all the object instantiation, but it was circumventing a lot of other logic, too. Before starting a major revision, I needed more evidence that object overhead was indeed one of the performance issues.
I created 2 pages that do exactly the same thing: one page reads an XML file of U.S. state data and loops through it to find the Great Lakes State (Michigan) and the Keystone State (Pennsylvania). One page creates a state object for each record in the XML, and the other just works with the XML data directly:
- Using objects: 129 milliseconds
- Without objects: 1006 milliseconds
(Times listed are averages for 1000 runs. The file are here: ColdFusion objects performance test)
Does this mean developers should avoid object-oriented code in ColdFusion? I don’t think so. But I don’t think developers should create objects willy-nilly when they aren’t necessary. The room reservation system, for example, doesn’t need to create 80 reservation objects just to display a list, but it makes sense to create a single reservation object once the user drills down to view or edit the specifics of a single reservation.
A few updates:
1. I had debugging output on for these tests. Everything appears to run faster when debugging output is turned off.
2. A good rule-of-thumb is: don’t create unnecessary objects! In the case of the room reservation tool, we already had a perfectly good ColdFusion query object with all the data we needed. There was no reason to turn every line of the query into its own object with various properties and methods.