填充阵列时的显着时间差异(Coldfusion vs Railo)
Significant difference in time while populating arrays (Coldfusion vs Railo)
在一些开发过程中,我 运行 遇到了连接字符串的问题,手动连接字符串而不是本地函数时看起来很慢
<cfset start = gettickcount()>
<cfset dummyArray = ArrayNew(1) />
<cfset concatedString = "" />
<cfset concatenatedByFunctionString = "" />
<cfloop from="1" to="100000" index="i">
<cfset arrayAppend(dummyArray, RandRange(1000000, 9999999)) />
</cfloop>
<cfoutput>Prepping data: #(gettickcount() - start)/1000# seconds<br/></cfoutput>
<cfset start = gettickcount()>
<cfloop from="1" to="100000" index="j">
<cfset concatedString = concatedString & dummyArray[j] />
</cfloop>
<cfoutput>concatenating data in loop: #(gettickcount() - start)/1000# seconds<br/></cfoutput>
<cfset start = gettickcount()>
<cfset concatenatedByFunctionString = arraytoList(dummyArray,'')/>
<cfoutput>concatenating data in arraytoList function: #(gettickcount() - start)/1000# seconds<br/></cfoutput>
<cfif structKeyExists(url,'debug')>
in loop:<br/>
<cfdump var="#concatedString#"/>
in function:<br/>
<cfdump var="#concatenatedByFunctionString#"/>
</cfif>
但这不是问题所在。当您 运行 在 Coldfusion 中使用此脚本时,准备数据所需的时间约为 150 毫秒,而在 Railo 中则超过 3000 毫秒。当用 cfset 替换 ArrayAppend 时,循环变得更快。
知道我做错了什么吗?
编辑:经过一些额外的测试,我们得出以下结果:
使用的脚本:
<cfset start = gettickcount()>
<cfloop from="1" to="10000" index="i">
</cfloop>
<cfoutput>Empty loop 10 000: #(gettickcount() - start)/1000# seconds<br/></cfoutput>
<cfset start = gettickcount()>
<cfloop from="1" to="100000" index="i">
</cfloop>
<cfoutput>Empty loop 100 000: #(gettickcount() - start)/1000# seconds<br/></cfoutput>
<cfset start = gettickcount()>
<cfloop from="1" to="100000" index="i">
<cfset local.tmp = 1/>
</cfloop>
<cfoutput>loop 100 000 cfset: #(gettickcount() - start)/1000# seconds<br/></cfoutput>
<cfset start = gettickcount()>
<cfscript>
string = CreateObject("java", "java.lang.String");
array = CreateObject("java", "java.lang.reflect.Array");
dummyArray = array.newInstance(string.getClass(), 10000);
</cfscript>
<cfloop from="0" to="9999" index="i">
<cfset array.set(dummyArray, i, "00000") />
</cfloop>
<cfoutput>loop 10 000 java array set: #(gettickcount() - start)/1000# seconds<br/></cfoutput>
<cfset start = gettickcount()>
<cfset dummyArray = ArrayNew(1) />
<cfloop from="1" to="100000" index="i">
<cfset arrayAppend(dummyArray, '00000') />
</cfloop>
<cfoutput>loop 100 000 arrayAppend: #(gettickcount() - start)/1000# seconds<br/></cfoutput>
<cfset start = gettickcount()>
<cfset dummyArray = ArrayNew(1) />
<cfloop from="1" to="100000" index="i">
<cfset dummyArray[i] = '00000' />
</cfloop>
<cfoutput>loop 100 000 array set via brackets: #(gettickcount() - start)/1000# seconds<br/></cfoutput>
输出:
Railo(4.2.1.008 最终版):
空循环 10 000:0.001 秒
空循环 100 000:0.013 秒
循环 100 000 cfset:0.05 秒
循环 10 000 java 数组集:8.095 秒
循环 100 000 arrayAppend:1.96 秒
通过括号设置循环 100 000 个数组:2.103 秒
Adobe CF 10:
空循环 10 000:0.002 秒
空循环 100 000:0.059 秒
循环 100 000 cfset:0.115 秒
循环 10 000 java 数组集:0.014 秒
循环 100 000 arrayAppend:0.139 秒
通过括号设置循环 100 000 个数组:0.15 秒
对此有任何见解/想法吗?
谢谢。
编辑2:
我的真实世界问题:
<cfinclude template="/queries/pr_web_shop_country_seo.cfm" >
<cfloop query="qry_web_shop_country_seo">
<cfif qry_web_shop_country_seo.generate_sitemap eq 1>
<cfset types_to_generate = ArrayNew(1) />
<cfset types_to_generate[1] = "PRODUCTS" />
<cfset indexList = ArrayNew(1) />
<cfset locale = qry_web_shop_country_seo.country_code />
<cfset id_language = qry_web_shop_country_seo.id_language_default />
<cfset file_suffix = "-" & replace(qry_web_shop_country_seo.url_domain,'.','-','ALL') & ((qry_web_shop_country_seo.url_suffix eq "")? "" : "-" & qry_web_shop_country_seo.url_suffix) />
<cfinclude template="/queries/pr_seo_urls.cfm">
<cfloop array="#types_to_generate#" index="type">
<cfswitch expression="#type#">
<cfcase value="PRODUCTS">
<cfset productData = ArrayNew(2)>
<cfset counter = 1>
<cfloop query="qry_seo_urls">
<cfif qry_seo_urls.source eq 'PRODUCT'>
<cfset arrayAppend(
productData[Ceiling(counter/max_link_list)]
,url_prefix & qry_web_shop_country_seo.url_domain & qry_web_shop_country_seo.root & qry_seo_urls.seo_url)
/>
<cfset counter = counter + 1 />
</cfif>
</cfloop>
</cfcase>
</cfswitch>
</cfloop>
</cfif>
</cfloop>
如果您正在寻找最快的解决方案,请尝试使用 java.util.ArrayList
。我在 Lucee 4.5 上试过它,它表现不错,所以可能适合你的需要。
<cfset start = gettickcount()>
<cfset dummyArray = createObject("java", "java.util.ArrayList")>
<cfloop from="0" to="9999" index="i">
<cfset dummyArray.add("00000")>
</cfloop>
<cfoutput>
loop 10,000 java.util.ArrayList add: #(gettickcount() - start)/1000# seconds
</cfoutput>
在一些开发过程中,我 运行 遇到了连接字符串的问题,手动连接字符串而不是本地函数时看起来很慢
<cfset start = gettickcount()>
<cfset dummyArray = ArrayNew(1) />
<cfset concatedString = "" />
<cfset concatenatedByFunctionString = "" />
<cfloop from="1" to="100000" index="i">
<cfset arrayAppend(dummyArray, RandRange(1000000, 9999999)) />
</cfloop>
<cfoutput>Prepping data: #(gettickcount() - start)/1000# seconds<br/></cfoutput>
<cfset start = gettickcount()>
<cfloop from="1" to="100000" index="j">
<cfset concatedString = concatedString & dummyArray[j] />
</cfloop>
<cfoutput>concatenating data in loop: #(gettickcount() - start)/1000# seconds<br/></cfoutput>
<cfset start = gettickcount()>
<cfset concatenatedByFunctionString = arraytoList(dummyArray,'')/>
<cfoutput>concatenating data in arraytoList function: #(gettickcount() - start)/1000# seconds<br/></cfoutput>
<cfif structKeyExists(url,'debug')>
in loop:<br/>
<cfdump var="#concatedString#"/>
in function:<br/>
<cfdump var="#concatenatedByFunctionString#"/>
</cfif>
但这不是问题所在。当您 运行 在 Coldfusion 中使用此脚本时,准备数据所需的时间约为 150 毫秒,而在 Railo 中则超过 3000 毫秒。当用 cfset 替换 ArrayAppend 时,循环变得更快。
知道我做错了什么吗?
编辑:经过一些额外的测试,我们得出以下结果:
使用的脚本:
<cfset start = gettickcount()>
<cfloop from="1" to="10000" index="i">
</cfloop>
<cfoutput>Empty loop 10 000: #(gettickcount() - start)/1000# seconds<br/></cfoutput>
<cfset start = gettickcount()>
<cfloop from="1" to="100000" index="i">
</cfloop>
<cfoutput>Empty loop 100 000: #(gettickcount() - start)/1000# seconds<br/></cfoutput>
<cfset start = gettickcount()>
<cfloop from="1" to="100000" index="i">
<cfset local.tmp = 1/>
</cfloop>
<cfoutput>loop 100 000 cfset: #(gettickcount() - start)/1000# seconds<br/></cfoutput>
<cfset start = gettickcount()>
<cfscript>
string = CreateObject("java", "java.lang.String");
array = CreateObject("java", "java.lang.reflect.Array");
dummyArray = array.newInstance(string.getClass(), 10000);
</cfscript>
<cfloop from="0" to="9999" index="i">
<cfset array.set(dummyArray, i, "00000") />
</cfloop>
<cfoutput>loop 10 000 java array set: #(gettickcount() - start)/1000# seconds<br/></cfoutput>
<cfset start = gettickcount()>
<cfset dummyArray = ArrayNew(1) />
<cfloop from="1" to="100000" index="i">
<cfset arrayAppend(dummyArray, '00000') />
</cfloop>
<cfoutput>loop 100 000 arrayAppend: #(gettickcount() - start)/1000# seconds<br/></cfoutput>
<cfset start = gettickcount()>
<cfset dummyArray = ArrayNew(1) />
<cfloop from="1" to="100000" index="i">
<cfset dummyArray[i] = '00000' />
</cfloop>
<cfoutput>loop 100 000 array set via brackets: #(gettickcount() - start)/1000# seconds<br/></cfoutput>
输出:
Railo(4.2.1.008 最终版):
空循环 10 000:0.001 秒
空循环 100 000:0.013 秒
循环 100 000 cfset:0.05 秒
循环 10 000 java 数组集:8.095 秒
循环 100 000 arrayAppend:1.96 秒
通过括号设置循环 100 000 个数组:2.103 秒
Adobe CF 10:
空循环 10 000:0.002 秒
空循环 100 000:0.059 秒
循环 100 000 cfset:0.115 秒
循环 10 000 java 数组集:0.014 秒
循环 100 000 arrayAppend:0.139 秒
通过括号设置循环 100 000 个数组:0.15 秒
对此有任何见解/想法吗?
谢谢。
编辑2:
我的真实世界问题:
<cfinclude template="/queries/pr_web_shop_country_seo.cfm" >
<cfloop query="qry_web_shop_country_seo">
<cfif qry_web_shop_country_seo.generate_sitemap eq 1>
<cfset types_to_generate = ArrayNew(1) />
<cfset types_to_generate[1] = "PRODUCTS" />
<cfset indexList = ArrayNew(1) />
<cfset locale = qry_web_shop_country_seo.country_code />
<cfset id_language = qry_web_shop_country_seo.id_language_default />
<cfset file_suffix = "-" & replace(qry_web_shop_country_seo.url_domain,'.','-','ALL') & ((qry_web_shop_country_seo.url_suffix eq "")? "" : "-" & qry_web_shop_country_seo.url_suffix) />
<cfinclude template="/queries/pr_seo_urls.cfm">
<cfloop array="#types_to_generate#" index="type">
<cfswitch expression="#type#">
<cfcase value="PRODUCTS">
<cfset productData = ArrayNew(2)>
<cfset counter = 1>
<cfloop query="qry_seo_urls">
<cfif qry_seo_urls.source eq 'PRODUCT'>
<cfset arrayAppend(
productData[Ceiling(counter/max_link_list)]
,url_prefix & qry_web_shop_country_seo.url_domain & qry_web_shop_country_seo.root & qry_seo_urls.seo_url)
/>
<cfset counter = counter + 1 />
</cfif>
</cfloop>
</cfcase>
</cfswitch>
</cfloop>
</cfif>
</cfloop>
如果您正在寻找最快的解决方案,请尝试使用 java.util.ArrayList
。我在 Lucee 4.5 上试过它,它表现不错,所以可能适合你的需要。
<cfset start = gettickcount()>
<cfset dummyArray = createObject("java", "java.util.ArrayList")>
<cfloop from="0" to="9999" index="i">
<cfset dummyArray.add("00000")>
</cfloop>
<cfoutput>
loop 10,000 java.util.ArrayList add: #(gettickcount() - start)/1000# seconds
</cfoutput>