【发布时间】:2015-11-18 22:39:20
【问题描述】:
在一些开发过程中,我遇到了连接字符串的问题,这在手动而不是本机函数时似乎很慢
<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 数组追加: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 数组追加: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>
【问题讨论】:
-
你没有做错什么; Railo 的速度似乎比 ColdFusion 慢。您实际上在这里寻找什么样的答案?你有一个现实世界的问题,还是这只是理论上的?如果您遇到实际问题,请改写问题以仅关注实际问题,而不仅仅是循环解循环“性能”“测试”。
-
我们正在根据这一原则构建站点地图。我们正在循环大约 150.000 条记录。至于现实生活中的问题:如果这是 100K 循环的问题,我认为问题在 500 循环上是相同的,只是没有那么大。如果我们可以通过配置或其他方式改进这一点,这将意味着我们获得了大约 300 倍的改进,我认为这非常重要。这就是我正在寻找的答案。
-
@KennyG。凉爽的。因此,修改问题文本以实际提出问题。不要问一个理论问题:问一个真正的问题。也就是说,在这种情况下,如果它只是您真正要询问的技术,而不是“问题”本身,那么它可能更像是代码审查的一个问题。您遇到的唯一缓慢的情况是使用 Java 数组的情况,无论如何这都是一件奇怪的事情,并且偶尔脚本上的迭代超过 100k,8 秒并不需要担心。使用 CFML 数组的 1-2 秒要少得多。
-
@AdamCameron 根据对帖子的快速浏览,在进行代码审查之前需要对其进行澄清。 On-Topic CR 问题:“这是设计用于执行 XYZ 的工作代码,我希望它运行得更快,有什么建议吗?”。题外话 CR 问题:“这是我们已经研究/尝试过的潜在方法,这些是结果,为什么 A 和 B 比 C 和 D 更快?E/F 会更快吗?”
-
@AdamCameron:我知道在为最终用户处理数据时,无法通过单次交互来判断应用程序本身的时间差异。很可能您不会为前端用户循环处理 100K 记录。我们还使用 1K 记录测试了循环,在这些测试中,railo 似乎更快:0.002 对 0.008 秒。我确实觉得很奇怪,如果我们将数据乘以 100,它会从快 4 倍变为慢 15 倍。顺便说一句,这同样适用于 Lucee。但那是另一回事了。
标签: arrays performance coldfusion cfml railo