Performance of CFScript

by

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

7 Responses to “Performance of CFScript”

  1. Jon Wolski Says:

    “continue” – the one thing cfscript can do that CFML can’t.

  2. Dan Watt Says:

    Jon, actually CF9 adds

  3. Dan Watt Says:

    …. adds CFCONTINUE

  4. Brian Meloche Says:

    Awesome! I was just asking this very question today! Thanks for testing this! I figured that they performed about the same, but this seems to prove that. I’ll thank Kurt Wiersma, who pointed me to this article.

  5. Justin Carter Says:

    Would you mind doing a similar thing to compare the performance of tags and the CF9 equivalent “tags implemented as components”? e.g. cfquery tag vs. new Query()..

    From the small amount of testing I did, Query() was quite a bit slower than cfquery as soon as you have a query with more than a couple of parameterised values. I’d be very interested to see your same methodology applied to these new “objects” 🙂

  6. Dan Watt Says:

    Justin, I actually did the same the same test myself, and though I do not have the numbers right in front of me, doing Query() was about 30-40% slower than CFQUERY. If you look at query.cfc (found in WEB-INF/cfusion/CustomTags/com/adobe/coldfusion/query.cfc), it does a lot of heavy lifting before passing off to . In particular, it has its own SQL parser so that it can find the named parameters.

    The other tag wrappers, like mail, http, pdf all appear to be very lightweight wrappers on top of built-in tags. Query seems to be the only one that has a lot of code in it.

  7. Justin Carter Says:

    @Dan Cool, that’s the same conclusion I came to. It would be interesting to profile the query component to see if it’s just the string handling, or if there are other factors like the object instantiation (the component itself plus the objects it creates inside it), the use of cfinvoke, etc. It’s definitely much slower though, so here’s hoping for an improvement in CF10 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: