BlueDragon Blog
Here you'll find tips and information about making the most of BlueDragon, which offers several compelling implementation alternatives for your CFML applications. This blog was created originally by Charlie Arehart, who was New Atlanta CTO from 2003-2006.,He has since moved on to become an independent consultant but continues to answer comments raised in existing blog entries. BlueDragon continues, and you should look to the newer BlueDragon blog, from New Atlanta president, Vince Bonfanti, for more updated information.

Using a large loop to compare performance of coding choices? Think twice...

posted Monday, 16 January 2006

We all know that the common way to test whether approach "a" is better than "b" is to do the two things in a CFLOOP a million times or some such and compare the time spent. I've shown that if instead one instead tests the two approaches by using a load testing tool (perhaps running the request thousands of times), the differences between the two coding choices are wiped out in the noise of starting/stopping a request, etc. In such a case, it makes me wonder if such tweaks are worth the bother, unless indeed you are doing the given thing a million times in a loop.

This is how I started a discussion on a closed list of high-level CFML developers some months back, where a discussion had arisen about choosing one coding technique over another based on such loop testing. The subject has come up today on another list so I wanted to share the proposal here to point to on that thread (and for others to consider in general).

I had asked for feedback to that posting on that private list and got back nearly unanimous confirmation from some of the leading lights in the CFML industry. I've obtained permission from each to repeat their replies here.

Sean Corfield responded:

I've been arguing this exact same thing for years so I totally agree with you. Anyone who bases a code choice on the results of running some code fragment in a loop on their own workstation is living in a dream world!

Then Rob Munn wrote:

I like best practices, but I don't try to squeeze every millisecond out of every piece of code. I would rather build an app that can scale horizontally. I would rather focus my performance tuning on areas of code that are most widely used in an application....

To which Simon Horwith replied:

I have to agree that looking at syntax for ways to shave extra milliseconds is a low priority.  That's not to say it isn't important, though.  As was said, the database, SQL, and database connection settings is the first thing I'd look at. CF server settings in general are another biggie - having debugging turned on or off for example,can make a huge difference in performance (as can trusted cache and many other settings).  I also pay close attention to memory usage - particularly in a high traffic site.  Too much data in the session scope can bring a server to it's knees when a search engine begins crawling it.  I also look at response sizes.  I use CFSCRIPT a lot - not only because I find the syntax cleaner but also because of it's whitespace suppression.  Pages with huge blocks of whitespace don't return to the client as fast. Trying to shave milliseconds is a last resort in performance tuning, in my opinion.

Dave Watts concurred with my original proposition:

This has absolutely been my experience. First, the "loop a thousand times" testing process doesn't appear to correspond with load-testing results at all, in many cases. Second, these things tend to vary across versions of CF, so one way might be marginally faster with, say, CF 5 while another way might be faster with CFMX 6.1 and so on. Finally, and most important, these sorts of "premature optimization" things don't seem to do anything except distract the developer's focus from the real bottlenecks in an application.

I haven't encountered an application yet which couldn't benefit from further examination of the database schema and application caching mechanisms.

Finally Pete Freitag wrote:

One thing to keep in mind in the load test vs monster loop debate is that since CF engines use a JVM now, the hotspot compiler comes into play. The hotspot compiler optimizes the java byte code based on the frequency of execution. So when your doing a loop test you almost always going to invoke the hotspot compiler, and you are really just testing which code the hotspot can optimize better - but in the real world execution the function call may never end up in the hotspot.

So there you have it. Next time someone proposes that you "throw some code in a loop" to test its performance, consider sending them to this posting to let them ruminate on these thoughts. Granted, neither I nor they are offering any demonstrated proofs of our assertions.

Someone should, at some point, put together a real documented test case to prove it for the nay-sayers. Still, these conclusions comes from probably combined nearly 100 years of CFML experience. I think they deserve serious consideration.

Even so, I'm sure some will want to argue against this conclusion. That's what blog comments are for, right? :-) Fire away.




1. Steve Gustafson left...
Tuesday, 17 January 2006 8:10 pm :: http://blog.geopoly.com

You and the others are absolutely correct. If squeezing milliseconds out of an app is that important, there are better places to spend your time. These include database tuning, SQL tuning, JVM configuration, web server tuning, and even hardware choices.

The one exception I routinely see however is code that puts a query inside a loop ( typically output from another query ). I hear people say it works great in dev and is awful in production. Of course the dev DB loops through 5 records and the production db loops through 1,000!


2. Charlie Arehart left...
Tuesday, 17 January 2006 9:08 pm

Great point about the other "bigger hitter" opportunities for improvement. I should have elaborated on those and more. Thanks for doing so. As for the query within a loop, I'll note that it's also often a sign of a missed opportunity for a join, which would generally perform better. (Like so many things, "it depends", but we're talking in generalities here.)


3. a tester left...
Tuesday, 17 January 2006 9:53 pm

That may be true, but if you run analogous code in a loop between two languages, if one language is considerably faster than the other then I think this is still telling you something. This was the case when I ran BlueDragon.Net vs. native C# .Net doing the same exact thing.


4. Charlie Arehart left...
Tuesday, 17 January 2006 11:15 pm

Tester, I'd still argue that any test of code between two languages using a loop for comparison would be similarly contrived and lacking in validity. If a typical app once deployed would never do such a monster loop, then using this as a point of comparison is no better than the whole assertion made above. A load test would be the far more effective and valuable comparison.

(And be sure to compare apples and apples. Whether or not BD.NET compares favorably to native ASP.NET isn't generally as significant as whether it compares favorably to CFMX or the Java versions of BD. Even then, raw speed isn't the only benefit one may seek: BD.NET exists to help folks with legacy investments in CFML leverage the benefits of the .NET platform without rewriting code, while opening doors of integration between CFML and ASP.NET. We certainly don't begrudge anyone who wants to rewrite part or even eventually all of their CFML to ASP.NET, for whatever reason, at some point down the road. Anyway, let's not let this comment thread diverge from the main point of the blog entry, please.)


5. Doug left...
Wednesday, 18 January 2006 7:17 pm

Let me play devil's advocate here, despite the big names I'm arguing against. I can totally agree with the sentiment that over optimizing CF code is likely not worth the effort. But to argue against looping over code to determine which method is fastest (for your given version of CF presumably) doesn't seem to make sense to me beyond that initial issue of "why bother".

You seemingly presume that the looping technique is only used for non-obvious tiny incremental comparisons that are negligable compared to the time to start/stop a request (hence the need to magnify it by looping over it), but that's not neccessarily the case. To someone who simply doesn't know better than to put a query inside a loop, it would still be an enlightening technique. Even for discovering smaller incremental optimizations is could still be useful.

Faster is faster. If none of you ever heard of or used a best practice, you'd all be writing unoptimized code. The point is to assimilate this knowledge into your everyday practices and code more efficient apps, presumably without sacrificing other things like readbility. Not to be elite and correct other people's code to shave off miliseconds after the fact. Knowledge is power and if the looping scenario can teach you a few more optimizations that you didn't know from the lack of those very "best practices" being etched into your brain or sitting on your desk, then so be it. If all you ever concern yourself with is larger performance areas, such as database/query optimizations, you may see more results and still code solid apps, but the additional knowledge and effort to make CF optimizations does not have to be mutually exclusive with database optimizations, etc.

The fact that the effect of a single optimization might be lost in the real world due to the time (or noise) "of starting/stopping a request" is irrelevant except to put the potential "gains" into perspecitve. I suggest the looping scenario is still useful. Throw the numbers out the window except to compare which method is faster and remember the result. Multiplied by a dozen or so instances PER REQUEST (not just a one line comparison) and multiplied out by thousands of requests, poor coding choices may still bite you in the rear.

In closing, I agree with the sentiment. I agree that such "tweaks" may not be worth the bother, but you don't have to "tweak" if you've done it the faster way in the first place. I do not agree that the looping scenario is flawed or without merit as long as it is used only as a means of discovering optimizations and not neccessarily quantifying them explicitly. Stats can always be misused and misrepresented anyway.

As for Pete's mention of the hotspot compiler... I don't know how to assimilate that into all of this. It sounds like the end result MAY be mirrored in the production environment or may not, depending on circumstances.


6. Charlie Arehart left...
Thursday, 19 January 2006 10:09 am

Doug (don't know which Doug in the CFML world this is), I'm sorry to hear you argue for the conventional wisdom on this. It doesn't seem that you're giving credibility to the very heart of the proposal: that a loop just DOES NOT equate to the same behavior/performance cost as a real load test.

I appreciate that it seems counter-intuitive on first look: CPU time is CPU time. I'm just telling you that I've done testing that proved this, and these other folks have concurred from their own experience. (I don't have the details at hand as it was several months ago, but this isn't like I'm making some rash assertion of BD against CF so I hope you'll give us/me the benefit of the doubt. This proposal is universal across any web application, not just CFML.)

The others who concurred are not likely to see your reply or my response here, so we may not have as much back and forth to elaborate on this as we might if this was on a mailing list. But again the point was that I asked this on a private list with a lot of VERY experienced CFML folks, and these were the significant responses. (And they're not the sort to agree with me just because I proposed it: on the contrary, they and others wouldn't have thought twice to argue that it was bunk. They didn't.)

As I said in my closing above, I realize that some will demand proof before they'll accept the proposal. I appreciate that. I can't take the time now, but let's see if you or others force that hand. :-)


7. Doug left...
Friday, 20 January 2006 8:35 am

Well sure, I'd like to see proof then. I understand there are instances where the test would not be valid, but that doesn't mean it doesn't have valid uses. From what you're saying, it sounds like the test is not valid period, so I'd like to know exactly why.


8. Charlie Arehart left...
Wednesday, 23 August 2006 4:54 pm

I know it's been a few months since I last commented on this, and I didn't mean to leave Doug hanging. I just couldn't then (or before now) give time to putting together a test suite to document my assertions. I do plan to have that time next week, finally, for anyone still following along.

I've also reread Doug's next to last (long) comment, and there's one thing I didn't say back in January. You do make a good point in asking why not always adopt an approach if loop testing has shown it to be faster. I don't dispute that.

My real bone of contention is when people take the observations from such tests and then choose to (or argue one should) rewrite existing code to adopt the tweak. I would argue that it's THAT which should be avoided, because you don't know (without real world load testing, according to my argument) whether the change will really be of any benefit.

But sure, if it leads you to think you should choose one over another in the future, there's nothing wrong with that. But if you go further and start telling others that they also should always choose that approach over another, I would again argue that if real world testing doesn't show you using that tweak more than a couple times in a request, or using it in a loop, then even THEN it may still not be worth making big noise about. It's THAT use of loop testing that I've always felt was fallacious, leading to a simplistic perspective on the value of some tweak.

Sometimes, especially if the alternative would be unclear to the average reader, it still just may not be worth the bother. In such a case, I'd again argue it's only warranted if it's REALLY proven to lead to a benefit in your app. I'm just arguing for the value of real world load testing, as opposed to relying on conventional wisdom or worse, old wives tales. :-)


9. Student Management Guy left...
Saturday, 2 September 2006 2:06 am :: http://tuggle.it

"Premature optimization is the root of all evil." ~Donald Knuth


10. fee left...
Monday, 16 April 2007 3:49 pm :: http://www.blog-gu.com

Well sure, I'd like to see proof then. I understand there are instances where the test would not be valid, but that doesn't mean it doesn't have valid uses. From what you're saying, it sounds like the test is not valid period, so I'd like to know exactly why.


11. Charlie Arehart left...
Monday, 16 April 2007 6:53 pm :: http://www.carehart.org

Fee, I do hope to oblige you and others at some point with a documented test case, but until then, can I remind you that this is not just my opinion but one shared by several leading lights in the CFML tuning world. Do you really want to argue against them all so readily?

The point being made is that large loop testing is a fallacy that you shouldn't rely upon. I simply recommend that you (and anyone else with your position) consider doing your own testing with a real load before relying on any conclusion you'd make from a large loop.

If you want to ignore that, feel free, but just know that you do so at a risk you've been warned about. Anyway, yes, I will endeavor to put together a meaningful test. Just have a lot on my plate so this hasn't made it to the top of my priority list. (If you or anyone else wants to disprove it with a comparative test, I welcome those comments, too.)

BTW, this is now me answering as no longer working for New Atlanta. Of course, the blog entry is generic so applies as readily to CF as to BD. I just want to be clear that in my responding, I do so as an independent consultant now. If I do setup a test, I'll bring this all up anew in my own blog, at carehart.org.