Thursday, February 15, 2007

Performance Tips : ColdFusion List

how many of you have written/seen code like this?

<cfset mylist="jan,feb,mar,apr,may,jun,jul,sep,oct,nov,dec">
<cfloop from="1" to=#ListLen(mylist)# index="i">
<cfset month = ListGetAt(mylist, i)>
<!--- do something with this month --->
<cfoutput>#month#</cfoutput>
</cfloop>

While there is nothing wrong with it syntactically or functionally, performance wise it is very poor. Why? ColdFusion list is nothing but String (delimited by delimiter). ColdFusion does not have any way to build any intelligence to keep it in any other datastructure because you can use it like a normal string also. So what happens when you call any List function on this string? We parse the string using the delimiter and get the delimited tokens and process that.
Now lets take ListGetAt(list, index) function. It will keep parsing and getting the token unless it reaches the required index. Imagine doing in a loop. We will be parsing the same string again and again and traversing from the beginning everytime till we reach the next loop index. So, in the Nth iteration, it will start from beginning and tokenize N times. Thus by the time you have completed the loop, you have parsed/tokenized the string N*(N+1)/2 times. Isn't that too costly? Lesson - Never ever use ListGetAt() in a loop. Either iterate using OR convert the list into array using ListToArray() and iterate over it. Using cfloop is the most optimized way to do this.

Even if you are not iterating over list but you need to call ListGetAt() many times, it is better to convert it to array and then search the index in that.

Same thing applies to search functions like ListFind, ListContains etc. If you need to call these multiple times on the same list, you will be better off converting the list to array and searching in that.

If you need to append many items to the list, then also you will get a better performance by converting the list to array and doing all appends on that.

This does not mean you should not use list at all or you should always convert the list to array and work on that. If the number of operations that you are doing on the list is less, you should stick to list because converting the list to array is also costly. If you are inserting an element in the middle of list, list will be better than array in most cases.

3 comments:

Tjarko Rikkerink said...

Why not use:

#LSdateformat(month(now()),'mmm')# for Feb

OR

#LSdateformat(month(now()),'mmmm')# for Februari

dp said...

Hi,
I have a question regarding White space management:
I have read your and other's suggestion about setting white space management in CF admin, but in our setup environment (WebLogic + ColdFusion 7.0.2), under settings; I do not have option to turn-on white space management. I also read in one of the blogs to modify neo-runtime.xml with first attribute to "true", and after setting this, still I do not see option in CF Admin.
Can you tell me what I need to do to have white space management option available in CF Admin?

Thanks,
-Dipak

Matt said...

And this would be even better...

<cfset mylist="jan,feb,mar,apr,may,jun,jul,sep,oct,nov,dec">
<cfloop list="#mylist#" index="month">
<cfoutput>#month#<br></cfoutput>
</cfloop>

Thanks,
Matt