填充阵列时的显着时间差异(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>