Значительная разница во времени при заполнении массивов (Coldfusion и 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 мс. При замене ArrayAppend на cfset цикл становится намного быстрее.

Любая идея о том, что я делаю неправильно?

редактировать: после некоторого дополнительного тестирования мы пришли к следующим результатам:

Используемый скрипт:

<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 final):
Пустой цикл 10 000: 0,001 секунды
Пустой цикл 100 000: 0,013 секунды
Цикл 100 000 cfset: 0,05 секунды
Цикл 10 000 java array set: 8,095 секунды
loop 100 000 arrayAppend: 1,96 секунды
loop 100 000 array set через скобки: 2,103 секунды



Adobe CF 10:
Пустой цикл 10 000: 0,002 секунды
Пустой цикл 100 000: 0,059 секунды
Цикл 100 000 cfset: 0,115 секунды
Цикл 10 000 java array set: 0,014 секунды
loop 100 000 arrayAppend: 0,139 секунды
loop 100 000 array set через скобки: 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>

person Kenny G.    schedule 18.11.2015    source источник
comment
Вы не делаете ничего плохого; Кажется, что Railo просто медленнее, чем ColdFusion. Какой ответ вы на самом деле ищете здесь? У вас есть реальная проблема, или это все только теория? Если у вас есть реальная проблема, переформулируйте вопрос, чтобы сосредоточиться только на этой реальной проблеме, а не только на тестах производительности цикл за циклом.   -  person Adam Cameron    schedule 18.11.2015
comment
Мы строим карты сайта по этому принципу. мы зацикливаем более 150 000 записей прибл. Что касается проблем в реальной жизни: если это проблема на 100 000 циклов, я представляю, что проблема такая же на 500 циклах, просто не такая большая. Если мы сможем улучшить это с помощью конфигурации или чего-то еще, это будет означать, что мы получим улучшение примерно в 300 раз, что я считаю очень значительным. Это ответ, который я ищу.   -  person Kenny G.    schedule 18.11.2015
comment
@КенниГ. Прохладный. Поэтому измените текст вопроса, чтобы задать его. Не задавайте теоретический вопрос: задавайте настоящий вопрос. Тем не менее, в этом случае это может быть больше вопрос для проверки кода, если это просто техника, о которой вы действительно спрашиваете, а не проблема как таковая. Единственный медленный случай, который у вас есть, - это тот, который использует массивы Java, что в любом случае странно, и более 100 000 итераций в случайном сценарии, 8 секунд не о чем беспокоиться. Гораздо меньше 1-2 секунд при использовании массивов CFML.   -  person Adam Cameron    schedule 18.11.2015
comment
@AdamCameron Судя по быстрому просмотру сообщения, его необходимо уточнить, прежде чем переходить к проверке кода. Вопрос по теме CR: Вот рабочий код, предназначенный для выполнения XYZ, я хотел бы, чтобы он работал быстрее, есть предложения? Вопрос CR не по теме: Вот потенциальные подходы, которые мы рассмотрели / попробовали, вот результаты, почему A и B быстрее, чем C и D? Будет ли E/F еще быстрее?   -  person Kaz    schedule 18.11.2015
comment
@AdamCameron: я знаю, что разницу во времени в самом приложении нельзя определить по отдельным взаимодействиям при обработке данных для конечного пользователя. скорее всего, вы не будете обрабатывать 100 000 записей в цикле для внешнего пользователя. Мы также протестировали циклы с 1K Records, и в этих тестах railo кажется быстрее: 0,002 против 0,008 секунды. Я нахожу странным, что если мы умножим данные на 100, они будут идти от 4 раз быстрее до 15 раз медленнее. Кстати, то же самое относится и к Люси. Но это другое дело.   -  person Kenny G.    schedule 18.11.2015
comment
@КенниГ. Я не утверждаю, что это не актуальная и интересная тема, но это не дискуссионный форум, это сайт вопросов и ответов. На данный момент вы на самом деле не задаете действительный, реальный вопрос. Однако я говорил это уже несколько раз, так что если вы действительно что-то не предпримете, я ухожу.   -  person Adam Cameron    schedule 18.11.2015
comment
Если вы ищете самое быстрое решение, то я только что попробовал dummyArray = createObject("java", "java.util.ArrayList"); dummyArray.add("00000") на Lucee 4.5, и это работает хорошо.   -  person John Whish    schedule 18.11.2015
comment
@JohnWhish: я только что проверил это, и это действительно дает много улучшений по сравнению с обычной реализацией. Спасибо за этот ценный ответ. Можете ли вы опубликовать это как решение? Спасибо, Кенни.   -  person Kenny G.    schedule 18.11.2015
comment
Недавно у меня была такая же проблема в реальном мире (карты сайта), и я был удивлен, обнаружив, что объединение insidecfsavecontent было быстрее, чем использование массивов для построения строк: cfsimplicity.com/101/string-concatenation-in-lucee   -  person CfSimplicity    schedule 21.11.2015
comment
@CfSimplicity: спасибо за информацию, я попробую это в следующем случае. (я доволен скоростью, которую мы получаем от arraytolist, как сейчас).   -  person Kenny G.    schedule 24.11.2015


Ответы (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>
person John Whish    schedule 18.11.2015
comment
Глядя на реальный код выше, это не лучший кандидат для повышения производительности. Мне кажется, что слишком много данных извлекается слишком много раз, и лучшим решением было бы передать большую часть обработки обратно в БД, а не заставлять Railo все отсеивать. Вот почему я попросил задать этот вопрос, поскольку у меня есть конкретная проблема, которую необходимо решить, а не предопределять, на что следует обратить внимание, а затем сосредоточиться на этом. Что в данном случае, вероятно, не лучший подход с самого начала. - person Adam Cameron; 19.11.2015
comment
Справедливости ради, из комментариев к вопросу я сделал предположение, что они пытаются создать XML-файл карты сайта, в котором вы можете просматривать множество данных. Я попытался ответить на поставленный вопрос, хотя понимаю вашу точку зрения, что здесь может быть более широкая картина. - person John Whish; 19.11.2015
comment
Да, @john-whish, это было больше направлено на ОП, чем на тебя. Еще информация для вас. - person Adam Cameron; 19.11.2015
comment
@AdamCameron: я понимаю, что вы хотите вернуть обработку обратно в БД. Но поскольку само получение уже превысило требуемый срок, я не хочу усложнять мысли. Из-за настройки системы URL-адресов SEO это просто невозможно (время и ресурсы в реальных решениях). Вот почему я хотел решение cfml в качестве первого выбора. Учитывая тот факт, что у меня есть это решение сейчас и я сократил время обработки примерно на 2/3, я доволен этим. - person Kenny G.; 23.11.2015