Archive for September, 2011

Performance of CFScript

September 9, 2011

I have been developing ColdFusion on and off for about 10 years, and one topic that has been controversial the entire time is CFScript. The arguments go back and forth: ‘It’s too slow’, ‘it’s not ColdFusion’, ‘It looks like Javascript, but isn’t’.

On our team, the majority of our code is written in plain CFML. With new team members coming onboard with stronger backgrounds in Java-like languages, more and more CFScript is starting to show up, especially in the business-tier. The question of performance has come up, and though we do not have real numbers to back it up, the general consensus is that the performance difference is negligible, and each team can choose if they want to use CFML or CFScript going forward.

Not satisfied with a general feeling, I set out to conduct a very simple test, and see what ColdFusion does behind the scenes when compiling a simple component in CFML, and the same component written in CFScript. The component I came up with has a single function, with a single numeric argument. It then loops a variable number of times, constructs a struct, and does some simple math.

First, the CFML version. I added a suppressWhitespace=”true” directive around the component, in addition to output=”false”, to be completely sure that whitespace would not be emitted.

<cfcomponent output="false">
<cfprocessingdirective suppressWhitespace="true">
	<cffunction access="public" name="doStuff" returntype="void"  output="false">
		<cfargument name="iterations" type="numeric" required="true" />
		<cfloop from="1" to="#arguments.iterations#" index="local.i">
			<cfset local.myStruct = {a=1,b=local.i}/>
			<cfset local.myStruct.c = local.myStruct.a*local.myStruct.b/>
		</cfloop>
	</cffunction>
</cfprocessingdirective>
</cfcomponent>

Next up, CFScript. Notice there is no output=’false’ or suppressWhitespace equivalent. As I will show in a moment, CFScript components do not emit whitespace.

component {
	public void function doStuff(required numeric iterations){
		for (local.i = 1; local.i <= arguments.iterations; local.i++) {
			local.myStruct = {a=1,b=local.i};
			local.myStruct.c = local.myStruct.a*local.myStruct.b;
		}
	}
}

I turned on ‘Component cache’ and ‘Save class files’ in the ColdFusion Administrator, and ran the resulting .class files through the JAD decompiler.

The results of the decompilation don’t look the greatest here on WordPress, so here are links to the resulting decompiled Java classes:

A few observations:

  • The CFML version produces a runPage() method that has a lot of logic dealing with the cfprocessingdirective tag
  • Even with output=false and suppresswhitespace, the CFML version has several calls of the format _whitespace(out, “\r\n\t\t\t”);. With the suppresswhitespace in place, this still results in several function calls in the ColdFusion runtime, going from CfJspPage, to NeoPageContext, to CFOutput, before finally deciding to throw it away.
  • CFScript has no such whitespace method calls, so adding output=’false’ to CFScript is not necessary.
  • The CFML and CFScript versions of the FOR loop compile quite differently. The CFML version is somewhat tame at ‘for (; CfJspPage._checkCondition(t11, t15, t13); CfJspPage.checkRequestTimeout(“CFLOOP”))’, while the CFSCRIPT version is a little more complex, doing bit shifting in one place and a few extra casts.

Other than these differences, the compiled code is almost identical.

I also used JMeter to run simulated usage across the two components. With 8 simulated users across 4000 calls, each calling both CFCs in a random order and each passing 10,000 to the component (resulting in 40m total iterations), both averaged around 116ms per call, and consistently came within 3-4ms of each other.

This is far from an exhaustive comparison of CFML and CFScript. There are things that CFML can do that either you cannot do at all in CFScript, or have to jump through some hoops to do. Both flavors of the language have their places, and as for business-layer code that can be written without jumping through hoops, CFScript performs just as well as CFML.

Advertisements