2015-11-18 2 views
2

В течение некоторого развития я столкнулся в вопросе конкатенации строки, который кажется медленным, делая это вручную вместо родной функцииЗначительная разница во времени при заполнении массивов (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 окончательный):
Пустой цикл 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 сек



Любой Insight/идея по этому поводу?

Спасибо.

edit2:

моего реального мир вопрос:

<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> 
+1

Вы не делаете ничего плохого; Похоже, что Railo только медленнее ColdFusion. Какой ответ вы на самом деле ищете здесь? У вас есть проблема с реальным миром, или это все просто теоретическое? Если у вас есть проблема с реальным миром, переформулируйте вопрос, чтобы сосредоточиться именно на этой фактической проблеме, а не только на тестах производительности «loop-de-loop». –

+1

Мы строим карты сайта с этим принципом. мы зацикливаем более 150 000 записей прибл. Что касается проблем с реальной жизнью: если это проблема на 100-килограммовых петлях, я вижу, что проблема одинакова на 500 циклах, но не такая большая. Если мы сможем улучшить это с помощью конфигурации или чего-то еще, это будет означать, что мы получим улучшение в 300 раз, что я считаю очень значительным.Это ответ, который я ищу. –

+0

@ KennyG. Круто. Поэтому перепробуйте текст вопроса, чтобы действительно спросить об этом. Не задавайте теоретический вопрос: задайте * реальный вопрос. Тем не менее, в этом случае это может быть скорее вопросом для обзора кода, если это просто техника, о которой вы действительно спрашиваете, а не «проблема» как таковая. Единственный медленный случай, который у вас есть, - это тот, который использует Java-массивы, что является чем-то необычным, и что более 100 тыс. Итераций на случайном скрипте 8сec не о чем беспокоиться. Гораздо меньше 1-2 сек с использованием массивов CFML. –

ответ

2

Если вы ищете самое быстрое решение, то попробуйте использовать 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> 
+0

Глядя на код «реального мира» выше, это не лучший выбор для повышения производительности. Мне кажется, что слишком много данных извлекается слишком много раз, и лучшим решением было бы перевести большую часть обработки обратно в БД, вместо того, чтобы заставить Railo сорвать все это. Вот почему я попросил задать вопрос: «У меня есть эта конкретная проблема, которая требует решения», а не предопределяет то, на что нужно смотреть, а затем сосредоточившись на этом. В этом случае, вероятно, не самый лучший подход с самого начала. –

+1

Справедливая точка зрения, из комментариев по этому вопросу, я сделал предположение, что они пытаются создать файл Sitemap для XML, где вы могли бы перебирать множество данных. Я попытался ответить на поставленный вопрос, хотя я считаю, что здесь может быть более полная картина. –

+0

Да, @ john-whish, это было больше направлено на OP, чем вы. Больше FYI для вас. –

Смежные вопросы