Skip to main content
Ben Nadel at cf.Objective() 2012 (Minneapolis, MN) with: Ed Northby
Ben Nadel at cf.Objective() 2012 (Minneapolis, MN) with: Ed Northby

Testing Performance Overhead Of Creating Java Classes In Lucee CFML

By
Published in Comments (1)

UPDATE (2023-01-13): Please see the comments thread at the bottom. It seems there are definitely cases in which createObject() calls can become slow, having to do with where the JAR files are being loaded and what settings you are using in your application. The moral of the story is test test test your particular use-case, I suppose (though that feels like a very non-satisfactory answer given how generic the idea of loading Java classes is).


One of the most powerful features of ColdFusion is the fact that it is built on top of Java; and, at any time, we can reach down into the Java layer for additional functionality. The typical way in which we do this is to call createObject("java") and pass in a Java class name. Historically, I've tended to cache the returned Java class value, operating under the assumption that createObject() had a lot of overhead. But, I don't think I ever based this assumption on any concrete evidence. As such, I wanted to perform a trite performance exploration regarding the createObject() function in Lucee CFML.

As with all low-level performance experiments, this should be taken with a grain of salt seeing as I'm running it on my machine with no production traffic. That said, my goal here isn't to see absolute numbers but more to get a sense of relative performance between two different approaches.

To try this out, I'm going to experiment with a Static method on Java's Long class: .toString(). In my first loop, I'm going to call createObject() within every iteration. Then, in my second loop, I'm going to use a cached instance of the LongClass.

ASIDE: When I say "instance" here, it's a bit fuzzy - it's the instance of the class definition, not an instantiated instance of the class. This has to do with the ColdFusion abstraction of Java.

Note that in the following code, I'm outputting one value within each loop as a means to make sure that the ColdFusion compiler isn't trying to "optimize" the loop out of the code (seeing as it doesn't really do anything).

<cfscript>

	trialCount = 5;
	iterations = 1000000;

	echo( "Trials: #trialCount#, Iterations: #numberFormat( iterations )# <br />" );

	// ------------------------------------------------------------------------------- //
	// ------------------------------------------------------------------------------- //

	loop times = trialCount {

		echo( "<br />" );

		// -- TEST ONE --: Calling the createObject() function every time I need to access one
		// of the underlying Java methods.
		timer
			label = "Calling createObject() every time"
			type = "outline"
			{

			loop times = iterations {

				value = createObject( "java", "java.lang.Long" )
					.toString( randRange( 1, 100 ), 36 )
				;

			}

			echo( "Last value: #value#" );

		}

		// -- TEST TWO --: Caching the result of createObject() function, and then reusing
		// the cached class when I need to access one of the underlying Java methods.
		LongClass = createObject( "java", "java.lang.Long" );

		timer
			label = "Reusing Cached Class"
			type = "outline"
			{

			loop times = iterations {

				value = LongClass.toString( randRange( 1, 100 ), 36 );

			}

			echo( "Last value: #value#" );

		}

	}

</cfscript>

Each trial is running 1,000,000 loop iterations for each test. I had to jack this number of pretty high before I started to see any performance difference. And, when we run this ColdFusion code with 1 million iterations, we get the following output:

Testing showing that the average duration of each approach was within about 70ms (over 1 million iterations).

As you can see, there is some performance overhead to calling the createObject() function. However, it is extremely small, showing only about a 70ms aggregate overhead over the course of 1 million invocations. Essentially, there is no difference.

I'm glad I did this because caching the createObject() value adds complexity to my ColdFusion code. And, seeing that there's no meaningful overhead in calling the createObject() function, I'm going to stop trying to cache these values. Clearly, it was a premature optimization; and, I'm happy to be rid of it.

Want to use code from this post? Check out the license.

Reader Comments

15,841 Comments

After I posted this, several people over on Twitter (Brad Wood, Michael Born, James Moberg) pointed out that if you are loading Java classes from a 3rd-party JAR file, then calling createObject() can have a more significant impact.

Part of the reason that I wanted to use a Static Method in my demo was to try and isolate the Class definition cost from the Instantiation costs. But, it seems when you start dealing with dynamically loaded JAR files, things can start to get whacky.

Moral of the story, test test test your assumptions!

Post A Comment — I'd Love To Hear From You!

Post a Comment

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel