new udf: listReverse part 2

I got two comments with suggestions on my post yesterday regarding my UDF. Both solutions were considerably shorter in length and Bill Rawlinson even suggested dropping the arrays. Both suggestions seemed perfectly reasonable, but went against what I knew that manipulating lists. I always believed it is better to converet a list to an array then manipulate it, hence my solution. So after a quick, basic search on Google I came across the ColdFusion MX Coding Guidelines which states;
"Don't slavishly convert lists to arrays
Even though manipulating an array is generally faster than manipulating a list in CFMX, if you simply need to iterate over a list of items and process each one in turn the faster construct is <cfloop list="#itemList#" index="x"> ... </cfloop>. Don't convert 'itemList' to an array and then loop over that - it's not worth it because it probably won't be faster."


In a nutshell then:- if the list is short don't worry about it.

So I 'd thought I 'd test all three solutions. Todo this I set up an Application variable called "application.list" which held a list of numbers from 1 to 1000 seperated by a comma. Then on each test just reference this into a local variable called "list". Before I tested each page I loaded it up and hit refresh a couple of times. Then inbetween each test I waited 5 seconds. If you want to see the three sample .cfm pages I used click on "more" at the end of this post, alternatively you can download them here - please note they are uncommented.

The Test

ListReverse 1 = Bill Rawlinson suggestion.
ListReverse 2 = Devin suggestion.
ListReverse 3 = My suggestion.

ListReverse test, using "TOTAL EXECUTION TIME"
  ListReverse 1 (ms) ListReverse 2 (ms) ListReverse 3 (ms)
1. 282 156 16
2. 266 78 47
3. 265 93 16
Average 271 109 26.3

So from this, using the arrays was quicker, in some cases quite significantly. To explain this a bit better than I could I found a quote from RewindLife which stated:
"After reading the generated Java code I found that when you loop over a list by specifying the list attribute of a cfloop statement, ColdFusion optimizes the code by tokenizing the list only at the outset. If you were to use an indexed loop and listGetAt() each element, then ColdFusion would retokenize the list on each call and you'd start to get serious performance degradation.".

In conclusion then, if you are just looping over a list don't and not using other list functions then there is no need to worry with the ListToArray() function, else convert.

List Reverse 1

<cfapplication name="listChk">
\n<cfset list = application.list>
\n<cfscript>
\noutList = '';
\nfor (i=ListLen(list); i GT 0; i=i-1){
\n   outList = ListAppend(outList,ListGetAt(List,i));
\n   }
\n</cfscript>

List Reverse 2

<cfapplication name="listChk">
\n<cfset list = application.list>
\n<cfset listReverse=Reverse(list)>
\n<cfloop list="#listReverse#" index="i">
\n<cfset listReverse=Replace(listReverse, i, Reverse(i))>
\n</cfloop>

List Reverse 3

<cfapplication name="listChk">
\n<cfset list = application.list>
\n<cfscript>
\n   function listReverse(inList){
\n      var outArray = ArrayNew(1);
\n      var i=0;
\n      var j = 1;
\n      var inArray = listToArray(inList);   
\n   
\n      for (i=ArrayLen(inArray);i GT 0;i=i-1){
\n         outArray[j] = inArray[i];
\n         j = j + 1;
\n      }
\n      return arrayToList(outArray);
\n   }
\n</cfscript>

\n<cfset theList = listReverse(list)>

comments powered by Disqus