OCCASIONAL NEWSLETTER
May 2000
1. Some metrics...
Computers are incorporated in modern ice cream vending machines to enhance their functionality. Ice Cream Vending machines are manufactured by many companies. Your competition will try to overcome all requests for high-tech ice cream vending machines and credit card acceptorsадвокат по семейным делам для Вас
|
|
Here are some interesting metrics I obtained from running CF Server 4.01. Where I needed a database, I used CFSNIPPETS datasource (supplied with CF) so that anyone could replicate my tests. In all cases, I ran both tests 12 times, throwing out the top and bottom values and averaging the remaining ten.
Q. Which is faster when outputting a query, CFLOOP or CFOUTPUT with a QUERY property set?
A. Methodology:
***Test A ***
<cfquery datasource="cfsnippets" name="myQ">
SELECT * FROM Employees, Courses, Centers
</cfquery>
<cfset timeStart = GetTickCount()>
<cfset anArray = ArrayNew(1)>
<cfoutput query="myQ">
<cfset ArrayAppend(anArray,currentRow)>
</cfoutput>
<cfset timeStop = GetTickCount()>
<cfoutput>#Evaluate(timeStop-timeStart)#</cfoutput>
I ran the test 12 times, throwing out the top and bottom values. The average of the ten tests chosen was 785.1.
I then ran the following code to test for using a CFLOOP...
***Test B***
<cfquery datasource="cfsnippets" name="myQ">
SELECT * FROM Employees, Courses, Centers
</cfquery>
<cfoutput>
<cfset loopStart = GetTickCount()>
<cfset myArray = ArrayNew(1)>
<cfloop query="myQ">
<cfset ArrayAppend(myArray,currentRow)>
</cfloop>
<cfset loopStop = GetTickCount()>
#Evaluate(loopStop-loopStart)#</cfoutput>
Ran the tests 12 times again. Threw out top and bottom values. The average of the ten tests chosen was 785.3.
This would indicate that, contrary to conventional wisdom, there is no penalty for using cfloop in place of cfquery.
Q. When incrementing a value, what's faster -- IncrementValue or x = x+1?
A> Methodology:
***Test A***
<cfset startTime = GetTickCount()>
<cfset temp = 0>
<cfloop from="1" to="10000" index="i">
<cfset temp = IncrementValue(temp)>
</cfloop>
<cfset stopTime = GetTickCount()>
<cfoutput>#Evaluate(stopTime - startTime)#</cfoutput>
Ran the tests 12 times, etc. Average time was 1165.7
***Test B***
<cfset startTime = GetTickCount()>
<cfset temp = 0>
<cfloop from="1" to="10000" index="i">
<cfset temp = temp + 1>
</cfloop>
<cfset stopTime = GetTickCount()>
<cfoutput>#Evaluate(stopTime - startTime)#</cfoutput>
Average: 1001.6
Here, you can save 14% by using the code in Test B.
Q. Which is faster when adding to an array -- using ArrayAppend or setting the array directly?
A. Methodology:
***Test A***
<cfset startTime = GetTickCount()>
<cfset anArray=ArrayNew(2)>
<cfloop from="1" to="10000" index="i">
<cfset anArray[1][i] = i>
</cfloop>
<cfset stopTime = GetTickCount()>
<cfoutput>#Evaluate(stopTime - startTime)#</cfoutput>
After factoring out top and bottom values, average was 1087.6
***Test B***
<cfset startTime = GetTickCount()>
<cfset anArray=ArrayNew(2)>
<cfloop from="1" to="10000" index="i">
<cfset ArrayAppend(anArray[1],i)>
</cfloop>
<cfset stopTime = GetTickCount()>
<cfoutput>#Evaluate(stopTime - startTime)#</cfoutput>
Average now was 1214.8, indicating about a 10.5% time savings by NOT using ArrayAppend().
Q. Which is faster to create--an array of structures or a structure of arrays?
A. Methodology
***Test A***
<cfset startTime = GetTickCount()>
<cfset aStruct = StructNew()>
<cfset aStruct.firstName = ArrayNew(1)>
<cfset aStruct.lastName = ArrayNew(1)>
<cfset aStruct.city = ArrayNew(1)>
<cfloop from="1" to="10000" index="i">
<cfset aStruct.firstName[i] = 'Hal'>
<cfset aStruct.lastName[i] = 'Helms'>
<cfset aStruct.city[i] = 'Atlanta'>
</cfloop>
<cfset stopTime = GetTickCount()>
<cfoutput>#Evaluate(stopTime - startTime)#</cfoutput>
yielded an average of 2117 ms while this formulation
***Test B***
<cfset startTime = GetTickCount()>
<cfset anArray = ArrayNew(1)>
<cfloop from="1" to="10000" index="i">
<cfset aStruct = StructNew()>
<cfset aStruct.firstName = 'Hal'>
<cfset aStruct.lastName = 'Helms'>
<cfset aStruct.city = 'Atlanta'>
<cfset ArrayAppend(anArray,aStruct)>
</cfloop>
<cfset stopTime = GetTickCount()>
<cfoutput>#Evaluate(stopTime - startTime)#</cfoutput>
yielded an average of 3407.7. So you can gain a 38% time savings by using the formulation shown in Test A
Q.On the other hand, when retrieving data from the two tests immediately above...
A. Methodology:
***Test A***
<cfset startTime = GetTickCount()>
<cfset aStruct = StructNew()>
<cfset aStruct.firstName = ArrayNew(1)>
<cfset aStruct.lastName = ArrayNew(1)>
<cfset aStruct.city = ArrayNew(1)>
<cfloop from="1" to="10000" index="i">
<cfset aStruct.firstName[i] = 'Hal'>
<cfset aStruct.lastName[i] = 'Helms'>
<cfset aStruct.city[i] = 'Atlanta'>
</cfloop>
<cfloop collection="##aStruct##" item="aKey">
<cfloop from="1" to="#ArrayLen(Evaluate('aStruct.' & aKey))#" index="j">
<cfset temp = aStruct.firstName[j]>
</cfloop>
</cfloop>
<cfset stopTime = GetTickCount()>
<cfoutput>#Evaluate(stopTime - startTime)#</cfoutput>
gave an average of 5414.8 while this code
***Test B***
<cfset startTime = GetTickCount()>
<cfset anArray = ArrayNew(1)>
<cfloop from="1" to="10000" index="i">
<cfset aStruct = StructNew()>
<cfset aStruct.firstName = 'Hal'>
<cfset aStruct.lastName = 'Helms'>
<cfset aStruct.city = 'Atlanta'>
<cfset ArrayAppend(anArray,aStruct)>
</cfloop>
<cfset stopTime = GetTickCount()>
<cfoutput>
<cfloop from="1" to="#ArrayLen(anArray)#" index="j">
<cfset temp = anArray[j].firstName>
</cfloop>
#Evaluate(stopTime - startTime)#
</cfoutput>
yielded an average of 3424.9. So you can save about 37% if you use Test B. One method is faster when setting the values; the other is faster when retrieving them. I guess the Lord giveth and the Lord taketh away...
Q. Which is faster? x = x +1 or x = Evaluate(x +1)
A. Methodology:
***Test A***
<cfset startTime = GetTickCount()>
<cfset temp = 0>
<cfloop from="1" to="10000" index="i">
<cfset temp = Evaluate(temp + i)>
</cfloop>
<cfset stopTime = GetTickCount()>
<cfoutput>#Evaluate(stopTime - startTime)#</cfoutput>
gave average times of 3693.2 while this formulation...
***Test B***
<cfset startTime = GetTickCount()>
<cfset temp = 0>
<cfloop from="1" to="10000" index="i">
<cfset temp = temp + i>
</cfloop>
<cfset stopTime = GetTickCount()>
<cfoutput>#Evaluate(stopTime - startTime)#</cfoutput>
gave an average of 1065.6. So using Evaluate increased the time by over a factor of 3.
Q. Is it slower putting tags around an entire page?
A. Methodology
***Test***
<cfset startTime = GetTickCount()>
<cfset myArray = ArrayNew(1)>
<cfloop from="1" to="10000" index="i">
<cfset ArrayAppend(myArray, i)>
</cfloop>
<cfset stopTime = GetTickCount()>
This took #Evaluate(stopTime - startTime)#
Test A had CFOUTPUT tags around the entire page while Test B had CFOUTPUT tags only around the line with EVALUATE in it. Test A averaged 1119.5 while Test B averaged 1038.7, saving almost 14% of the processing time.
Q. How much slower is using WDDX to pass structure information?
A. Methodology
***Test***
<cfset aStruct = StructNew()>
<cfset aStruct.firstName = "hal">
<cfset aStruct.lastName = "helms">
<cfset aStruct.city = "atlanta">
<cfset aStruct.state = "ga">
<cfwddx action="CFML2WDDX" input="#aStruct#" output="wddxStruct">
<cfset startTime = GetTickCount()>
<cfwddx action="WDDX2CFML" input="#wddxStruct#" output="aStruct">
<cfloop collection="#aStruct#" item="aKey">
##aKey## --> #Evaluate('aStruct.' & aKey)#<br>
</cfloop>
<cfset stopTime = GetTickCount()>
<cfoutput>This took #Evaluate(stopTime - startTime)#</cfoutput>
This took an average of 5 ms to complete -- so short a time as to be entirely trivial. The moral: use WDDX when it's called for without worrying about performance penalty.
That's it for this edition. Next time, I'll talk about using bit functions to create user groups and permissions and what I learned from a recent clustering experience...
|