Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at cf.Objective() 2011 (Minneapolis, MN) with:

ColdFusion IIF() vs. CFIF

Posted by Ben Nadel
Tags: ColdFusion

To be honest, I have never used IIF(). The reason - it has been stated among various guru's best practices to not use it. As a result of that, I never really took the time to learn about it or see how it performed. As of late, though, there has been a lot of talk on the House of Fusion CF-Talk list about it and performance. There were some good blog posts about it by Phillip B. Holmes and Ashwin Mathew, but I needed to see for myself as I still wasn't 100% clear on what was going on.

On the other posts, there was a distinction between static evaluation and dynamic evaluation and that impact on performance. To test this, I have tried both method. Both use dynamic IIF() conditions, but one uses static delayed evaluation while the other used dynamic delayed evaluation.

Static Delayed Evaluation

In this test I check the performance of both CFIF and IIF() when the result in a static, non-changing value:

  • <!--- Run test on CFIF. --->
  • <cftimer label="CFIF" type="outline">
  •  
  • <!--- Loop 1000 times. --->
  • <cfloop index="intI" from="1" to="1000">
  •  
  • Molly Is
  • <cfif RandRange( 0, 1 )>
  • Sexy!
  • <cfelse>
  • Bodaciously Sexy!
  • </cfif>
  •  
  • </cfloop>
  •  
  • </cftimer>
  •  
  • <!--- Run test on IIF(). --->
  • <cftimer label="IFF()" type="outline">
  •  
  • <!--- Loop 1000 times. --->
  • <cfloop index="intI" from="1" to="1000">
  •  
  • Molly Is
  • #IIF(
  • RandRange( 0, 1 ),
  • """Sexy!""",
  • """Bodaciously Sexy!"""
  • )#
  •  
  • </cfloop>
  •  
  • </cftimer>

Both of the above test returned the static string "Sexy!" or "Bodaciously Sexy!". Notice how when using IIF() you have to treat it as string to be evaluated. If you do not do that, it will tell you that the variable "Sexy!" is undefined (actually it will tell you that "!") is not a valid token, but it is trying to evaluate the text.

As far as performance, over 1000 iterations, they both performed in about 15 ms, however, IIF() was able to run in 0ms more often than CFIF.

Dynamic Delayed Evaluation

In this test, I force the returned values of CFIF and IIF() to be dynamic so that no good optimization can be performed as compile time:

  • <!--- First, create an array of values. --->
  • <cfset arrValuesA = ArrayNew( 1 ) />
  • <cfset arrValuesA[ 1 ] = "Sexy!" />
  • <cfset arrValuesA[ 2 ] = "Bodaciously Sexy!" />
  •  
  • <!--- Create a second array of values. --->
  • <cfset arrValuesB = ArrayNew( 1 ) />
  • <cfset arrValuesB[ 1 ] = "Smart" />
  • <cfset arrValuesB[ 2 ] = "Funny" />
  •  
  • <!--- Perform the CFIF test. --->
  • <cftimer label="CFIF" type="outline">
  •  
  • <!--- Loop 1000 times. --->
  • <cfloop index="intI" from="1" to="1000">
  •  
  • Molly Is
  • <!--- This one must use dynamic a dynamic result. --->
  • <cfif RandRange( 0, 1 )>
  • #arrValuesA[ RandRange( 1, 2 ) ]#
  • <cfelse>
  • #arrValuesB[ RandRange( 1, 2 ) ]#
  • </cfif>
  •  
  • </cfloop>
  •  
  • </cftimer>
  •  
  • <!--- Perform the IIF() test. --->
  • <cftimer label="IFF()" type="outline">
  •  
  • <!--- Loop 1000 times. --->
  • <cfloop index="intI" from="1" to="1000">
  •  
  • Molly Is
  • <!--- This one must use dynamic delayed evaluation. --->
  • #IIF(
  • RandRange( 0, 1 ),
  • "arrValuesA[ RandRange( 1, 2 ) ]",
  • "arrValuesB[ RandRange( 1, 2 ) ]"
  • )# ...
  •  
  • </cfloop>
  •  
  • </cftimer>

Both of the above returned value sets must be dynamic. In this set of IIF() tests we do not need to escape any double quote values since we are referencing an array, not a static string value. Again, both of these tend to perform between 0ms and 15ms. Neither seem to trend towards better; both flip-flop between 0-15.

What does this all mean? It means that IIF(), in my opinion, is not the black sheep that I thought it was. It performs what seems to be equally well when compared to CFIF and can in many cases make for shorter code.

A note on the DE() method. I think this stands for "Delayed Evaluation" as it is delaying the evaluation of values passed to IIF() (ie. IIF( condition, DE("..."), DE("...") ). DE() escapes quotes for the delayed evaluation. In our first test, since we manually escaping quotes, we don't need to use DE(). But more than that, DE() does add a SLIGHT performance hit as it requires the use of two more method calls per iteration. But again, over 1000 iterations, this is still hardly noticeable.

Tweet This Groovy post by @BenNadel - ColdFusion IIF() vs. CFIF Thanks for making me feel special — you rock!


Reader Comments

It is my understanding that one of the main bonuses of IIF is it confines everything to one line. I have used it before when i have been deciding which function to use. For example: IIF(x,allow(),Disallow()).

Reply to this Comment

Peter,

I would tend to agree with you... but I think sometimes it depends on what you are trying to emphasize; if the IF statement is just a small property (ie. tag attribute) of a larger "idea" (ie. coldfusion tag), then I think using the IIF() in an attribute does not make it less readable.

But, certainly, personal preference can go either way.

Reply to this Comment

Would this same principle apply to the use of evaluate() function as well. I have often used evaluate() to parse dynamic variables and have recently been told that is bad for performance and found a lot of documentation online to support that statment. I never noticed it effecting any implementation I have ever done in a negative manner, and I did some very basic cfloop/gettickcount() type of benchmarking to see if there was a difference.

both ways took an average of 78ms and the only difference between the two scripts was that I used:
evaluate("GetEmpReview.item_1_#iIndex#")
instead of:
GetEmpReview["item_1_"& iIndex][currentRow]

Is there really a difference between using evaluate or using the second "Best Practice" method, or is it just something that was decided was best practice back when coldfusion was written in "C" and never questioned post MX?

Reply to this Comment

@Scott,

First off, sorry for taking so long to get back to your comment. I have two points to make about evaluate() that may or may not matter to you.

1. Speed. Is evaluate slower? Traditionally it is slower, or so I have been told. How much slower? In my small amount of testing, Evaluate() is slower IF you are running tens of thousands of method calls in a row. Only in such a large quantity will you begin to see speed differences. If you are talking about one line of code here and there on a site that doesn't have a million concurrent visitors, you won't notice anything.

2. Assertive Code. To me, this is more important than speed - it's about style. By using Evaluate(), it portrays the message that you don't realize that the a query column can be referenced dynamically (as in your second example). This to me, especially if I didn't know who you were and I was looking at your code, would come off as a lack of understanding of the language. By using the query-column, array notation, it makes a very strong statement about the fact that you know how to leverage ColdFusion's highly dynamic nature.

So, in summary, #1 really doesn't matter, especially if you are not dealing with a mammoth amount of traffic. And, #2 is a personal choice that may not even bother you.

Reply to this Comment

@Ben
Thanks for your response. I have done a little more testing and I feel that for the uses I put it to, it doesn't make a performance difference if I use evaluate or not. Your second comment is interesting though because I have been aware that both methods were possible for years, and I have used both methods in different situations. Many devlopers I have worked with or answered questions for on various forums don't even know how to use iif() or evaluate(), and get especially confused when de() is thrown into the mix. For me it has been simply a personal preference, because I think the evaluate is just a little bit more "readable". Similar to how some people prefer using cfscript over the normal tag based syntax, I can write and read both and I use both in different situations, but I prefer the tag based syntax (unless I'm writing a UDF or using certain com/java objects that lend themselves better to cfscript syntax). For me, when I am evaluating a developer to be on my staff, and reviewing any sample code they give me, I am more concerned with if the code works, is it efficient, readable, properly indented, commented, correct use of #'s, etc. I don't pass judgements on a programmers ability based on things that don't make a difference one way or another. Just to be clear I am not offended by your statement, I have definitely passed judgements on a programmers ability based on their code, I just wouldn't see this particular issue as defining a lack of understanding.

Reply to this Comment

@Scott,

It is all just personal preference. Certainly, code that works properly and is efficient is more important than minor details of minor consequence.

Reply to this Comment

IIf is useful in formfields such as checkboxes or radiogroup:

#IIf(query.field, DE('checked'),DE('')#

Using a CFIF to check that condition doesn't work when using CFINPUT. Additionally, IIf is good for alternating row colors all in one line, as somone mentioned.

Reply to this Comment

I think the best place to use IIF() is for SQL values. I love using the IIF() function!

I was just reading Coldfusions performance guidelines. Now, mind you these are for Coldfusion MX, but according to them...

"
Don't use iif()

Always use cfif/cfelse instead of iif(). It is significantly faster and more readable.
"

I don't know if this is still accurate.

Reply to this Comment

@Paul,

It's one of those things where you have to take it in context - we're talking milliseconds here in performance. If you use it a few times in a SQL statement, I don't think you would even come close to seeing a performance hit.

Of course, the busier your site is (thousands of concurrent users), you will want to start to tweak everywhere you can for optimization (maybe).

Reply to this Comment

I use it for alternate row color

<tr class="#IIF(currentrow MOD 2,DE('Color1'),DE('Color2'))#">

Reply to this Comment

I use IIF() in radio button inputs as well. Very useful. But today, I came across some code that lent itself to IIF() for consolidation of code...

Imaging checking 50 Session variables to set a local value corresponding to each:

<cfparam name="local.someVar1" default="" />

<cfif StructKeyExists(session, "someVar1")>
<cfset local.someVar1 = session.someVar1 />
</cfif>

(note: above is actually the cleaned up version)

I converted each of these 5-line statements to the following one line of code:

<cfset local.someVar1 = iif(StructKeyExists(session, "somevar1"), session.someVar1, "") />

Pretty useful, indeed.

Reply to this Comment

Just found your post!
Thanks for quoting me :)

I'd like to add that various prior versions of CF / CFMX didn't handle IIF() or DE() as well as it does today. I remember running tests on these as well as the evaluate() function and finding pretty big differences.

I suspect that Adobe has made performance improvements over the years.

Back in the day cfscript ran MUCH faster. With the latest version script is faster but not by much!

Thanks again for including me in your article!

Warmest,

Phillip Holmes

Reply to this Comment

Post A Comment

?
You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.