【问题标题】:Significant difference in time while populating arrays (Coldfusion vs Railo)填充阵列时的显着时间差异(Coldfusion vs Railo)
【发布时间】: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


【解决方案1】:

如果您正在寻找最快的解决方案,请尝试使用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>

【讨论】:

  • 看看上面的“真实世界”代码,这并不是性能改进的最佳选择。在我看来,太多的数据被提取了太多次,更好的解决方案是将更多的处理推回数据库,而不是让 Railo 将其全部清除。这就是为什么我要求将问题提出为“我有这个需要解决的具体问题”,而不是预先确定应该关注什么,然后专注于这一点。在这种情况下,这可能不是从一开始就最好的方法。
  • 公平点,从问题上的 cmets 来看,我假设他们正在尝试生成一个 XML 站点地图文件,您可以在其中循环大量数据。我试图回答提出的问题,尽管我同意你的观点,这里可能有更大的图景。
  • 是的,@john-whish,这比你更针对 OP。更多供您参考。
  • @AdamCameron:我明白你将处理带回数据库的意义。但是由于获取本身已经超过了想要的时间限制,我不想让想法变得更重。由于 seo urls 系统的设置,这根本不可能(现实世界解决方案中的时间和资源)。这就是为什么我想要一个 cfml 解决方案作为首选。鉴于我现在拥有该解决方案并且已经减少了大约 2/3 的处理时间,我对此感到满意。
猜你喜欢
  • 1970-01-01
  • 2017-12-14
  • 2023-02-08
  • 2018-01-20
  • 2015-02-09
  • 2015-01-09
  • 2019-02-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多