Избегайте ошибки кучи при зацикливании в coldfusion

Я пытаюсь перебрать массив 2-D с размерами 12000 * 20, и я постоянно получаю java.lang.OutOfMemoryError.

Сначала я подумал, что это может быть из-за размера кучи, поэтому я увеличил размер кучи, но все равно получал ту же ошибку. Итак, я запустил такой сборщик мусора:

<cflock name="checkMemory" type="exclusive" timeout="1" throwontimeout="yes">
    <cfset objSystem = CreateObject( "java", "java.lang.System" )>
    <cfset objSystem.gc()>
</cflock>

и я сбросил свободную память, которая была около 850MB:

<cfset runtime = CreateObject("java","java.lang.Runtime").getRuntime()>
<cfset freeMemory = runtime.freeMemory()>
<cfdump var="#freeMemory#" label="free">

Здесь я пытаюсь создать переменную XML, и во время цикла получаю ошибку кучи:

<cfxml variable="variables.XML">
  <cfoutput>
    <ROWS>
      <cfloop from="3" to="#arrayLen(local.array)#" index="i" step="1">
        <ROW>
          <cfloop from="1" to="#arrayLen(local.array[2])#" index="j" step="1">
            <#ucase(local.array[2][j])#>
              <![CDATA[#trim(local.array[i][j])#]]>
            </#ucase(local.array[2][j])#>
          </cfloop>
        </ROW>
      </cfloop>
    </ROWS>
  </cfoutput>
</cfxml> 

Это трассировка стека:

Есть ли лучшее решение, чтобы избежать такого зацикливания или устранить эту ошибку?

Я создал страницу cfm локально и добавил в нее следующие переменные:

Каждый раз, когда я обновлял эту страницу, размер свободной памяти уменьшался, пока я не запустил сборщик мусора. Я все еще пытаюсь понять, почему это происходит. Есть предложения по этому поводу?

<cfset runtime = CreateObject("java","java.lang.Runtime").getRuntime()>
<cfset freeMemory = runtime.freeMemory()>
<cfset totalMemory = runtime.totalMemory()>
<cfset maxMemory = runtime.maxMemory()>
<cfdump var="#freeMemory#" label="free">
<cfdump var="#totalMemory#" label="total">
<cfdump var="#maxMemory#" label="max">

Пожалуйста помоги. Заранее спасибо.

После предложений Адама Кэмерона, Dan Bracuk и Джеймс Моберг, я сделал следующее, и я не получаю ошибка кучи сейчас. Я подозреваю, что это было из-за тега 2-D, но не уверен.


person Beginner    schedule 24.03.2015    source источник
comment
@AdamCameron Я обновил свой вопрос.   -  person Adam Cameron    schedule 24.03.2015
comment
Итак, _1_ на самом деле не является подмассивом _2_, это просто другая область такой же длины, определяющая все узлы XML? Это может помочь показать, как вы создаете переменные массива, чтобы подтвердить это. У меня возникнет соблазн просто использовать UCase при заполнении array2, уменьшив, таким образом, 12000 * 20 * 2 вызовов функций.   -  person Beginner    schedule 24.03.2015
comment
@duncan - это массив [2], а не array2. Я поправил.   -  person duncan    schedule 24.03.2015
comment
то же самое и по сей день. Значение _1_ всегда одно и то же, каждый раз, когда вы вызываете его на своих 3..12000 итерациях.   -  person Beginner    schedule 24.03.2015
comment
@duncan Я вызываю его каждый раз, чтобы создать один и тот же узел в другом узле array[2][j]. И _2_ тоже динамичный. Так что мне нужно зацикливаться. Можно ли это сделать лучше?   -  person duncan    schedule 24.03.2015
comment
Выполните один цикл сразу над массивом [2], установив все значения в UCase, перед вашим основным циклом. Затем вы избавляетесь от необходимости дважды вызывать UCase на каждой из тысяч итераций последующих циклов.   -  person Beginner    schedule 24.03.2015
comment
Я изменил свой код, но все еще получаю ошибку кучи.   -  person duncan    schedule 24.03.2015
comment
Я бы, возможно, сначала построил строку, а затем преобразовал бы ее в XML, а не использовал бы CFXML, с которым у меня были проблемы с памятью в прошлом. Что вы делаете с этим XML после его создания? Также согласен с Дунканом: вам не нужно использовать ucase () одну и ту же строку несколько раз. Возможно также использовать для этого StringBuilder, а не String.   -  person Beginner    schedule 24.03.2015
comment
@AdamCameron Этот XML будет использоваться для целей отчетности и некоторых вставок в БД. Я изменил свой код и удалил несколько ucase. Я проверяю это с помощью _1_. Спасибо   -  person Adam Cameron    schedule 24.03.2015
comment
Проблема, похоже, в том, что вы пытаетесь иметь дело со слишком большим объемом данных. Посмотрите, откуда берутся эти данные, и посмотрите, можно ли их уменьшить. Если нет, поищите способ разбить его на части и обработать каждый кусок отдельно.   -  person Beginner    schedule 24.03.2015
comment
Итак, чтобы было ясно, действительно ли вам когда-либо понадобится XML, чтобы быть объектом XML CFML, или он будет использоваться отдельной системой (чтобы он мог просто оставаться строкой)?   -  person Dan Bracuk    schedule 24.03.2015
comment
Да, мне нужно создать объект CFML XML для другой системы.   -  person Adam Cameron    schedule 24.03.2015
comment
Что произойдет, если вы переместите CFOUTPUT за пределы ваших циклов, чтобы вы не вызывали его 240 000 раз. При построении больших строк я предпочитаю сбрасывать фрагменты строки в одномерный массив, а затем использовать ArrayToList (Array,) в конце. Затем выполните CFXML с последней единственной сгенерированной строкой вместо того, чтобы делать все это в блоке CFXML.   -  person Beginner    schedule 24.03.2015
comment
@JamesMoberg Я изменил свой код и переместил _1_.   -  person James Moberg    schedule 24.03.2015
comment
увеличил размер кучи до какой именно? вы используете 64-битную версию?   -  person Beginner    schedule 25.03.2015
comment
@Beginner Вы пробовали использовать массив для построения строки вне функции CFXML? Это поможет определить, связана ли проблема с генерацией XML или функцией CFXML. (Я предполагаю, что это с CFXML.)   -  person Henry    schedule 25.03.2015
comment
@JamesMoberg Я добавил свой ответ.   -  person James Moberg    schedule 25.03.2015
comment
java.lang.OutOfMemoryError в java.io.WinNTFileSystem.getBooleanAttributes (собственный метод) в java.io.File.exists (File.java:733) в coldfusion.xml.XmlProcessor.getSourceURL (XmlProcessor.javafusion:246) в coldfusion.javafusion:246) xml.XmlProcessor.parse (XmlProcessor.java:155) по адресу coldfusion.tagext.lang.XmlTag.doEndTag (XmlTag.java:85) по адресу cffeeds2ecfc1003675922 $ funcDEMO1._factor8 (C: \ component \ abc.cfc100eds: 1235endtag) funcDEMO1.runFunction (C: \ component \ abc.cfc: 1192) в coldfusion.runtime.UDFMethod.invoke (UDFMethod.java:472) в coldfusion.runtime.UDFMethod $ ReturnTypeFilter.invoke (UDFMethod.java) в coldfusion40.java. runtime. .invoke (UDFMethod.java:220) в coldfusion.runtime.CfJspPage._invokeUDF (CfJspPage.java:2582) в cffeeds2ecfc1 003675922 $ funcDEMO.runFunction (\ component \ abc.cfc: 935) в coldfusion.runtime.UDFMethod.invoke (UDFMethod.java:472) в coldfusion.runtime.UDFMethod $ ReturnTypeFilter.invoked (UDFMethod40) в UDFMethod5. runtime. .invoke (UDFMethod.java:517) в coldfusion.runtime.TemplateProxy.invoke (TemplateProxy.java:496) в coldfusion.runtime.TemplateProxy.invoke (TemplateProxy.java:355) в coldfusion.filter.ComponentFilter.invoke. java: 188) в coldfusion.filter.ApplicationFilter.invoke (ApplicationFilter.java:374) в coldfusion.filter.RequestMonitorFilter.invoke (RequestMonitorFilter.java:48) в coldfusion.filter.MonitoringFilter.invoke (Monitoring:Filter.invoke) при мониторинге coldfusion.filter.PathFilter.invoke (PathFilter.java:94) в Coldfusion.filter.ExceptionFilter.invoke (ExceptionFilter.java:70) в coldfusion.filter.ClientScopePersistenceFilter.invoke (ClientScopePersistenceFilter.java:28) в coldfusion. coldfilter.BrowserFilter.invoke (BrowserFilter.filter.java: .invoke (NoCacheFilter.java:46) в coldfusion.filter.GlobalsFilter.invoke (GlobalsFilter.java:38) в coldfusion.filter.DatasourceFilter.invoke (DatasourceFilter.java:22) в coldfusion.xml.rpletc.Cinvoke CFCServlet.java:139) в coldfusion.xml.rpc. CFCServlet.doPost (CFCServlet.java:290) в javax.servlet.http.HttpServlet.service (HttpServlet.java:760) в org.apache.axis.transport.http.AxisServletBase.serviceBase (AxisServletBase.service) (AxisServlet) .servlet.http.HttpServlet.service (HttpServlet.java:853) в coldfusion.bootstrap.BootstrapServlet.service (BootstrapServlet.java:89) в jrun.servlet.FilterChain.doFilter (FilterCharal.java: fusionreactor.filter.FusionReactorFilter.i (FusionReactorFilter.java:566) на com.intergral.fusionreactor.filter.FusionReactorFilter.c (FusionReactorFilter.java:258) на com.intergral.fusionreactor.filter.FusionReactor: 164) в jrun.servlet.FilterChain.doFilter (FilterChain.java:94) в coldfusion.monitor.event.MonitoringServletFilter.doFilter (MonitoringServletFilter.java:42) в coldfusion.bootstrap.BootstrapFilter.java:Filter.java: jrun.servlet.FilterChain.doFilter (FilterChain.java:94) в jrun.servlet.FilterC hain.service (FilterChain.java:101) в jrun.servlet.ServletInvoker.invoke (ServletInvoker.java:106) в jrun.servlet.JRunInvokerChain.invokeNext (JRunInvokerChain.java:42.Request.JrunInvokerChain.java:42.Request.Request (JrunInvokerChain.java:42.Request.Request.java: 42 .java: 286) по адресу jrun.servlet.ServletEngineService.dispatch (ServletEngineService.java:543) по адресу jrun.servlet.jrpp.JRunProxyService.invokeRunnable (JRunProxyService.java:203) в jrun.servlet.java:203) в jrun.Threado. java: 320) в jrunx.scheduler.ThreadPool $ ThreadThrottle.invokeRunnable (ThreadPool.java:428) в jrunx.scheduler.ThreadPool $ UpstreamMetrics.invokeRunnable (ThreadPool.java:266) в jrunx.scheduler. : 66)   -  person Beginner    schedule 26.03.2015


Ответы (1)


Преобразование всего элемента array[2] в верхний регистр:

Затем с помощью cfsavecontent для генерации строки xml:

<cfloop from="1" to="#arrayLen(local.array[2])#" index="i" step="1">
  <cfset local.array[2][i] = ucase(local.array[2][i])>
</cfloop>

Соответствующей частью кода здесь будет бит, который вы сокращаете как CFXML. Невозможно прокомментировать, что можно сделать, чтобы сделать этот код более удобным для использования памяти, не видя этого.

<cfsavecontent variable="local.xmlString">
  <?xml version="1.0" encoding="UTF-8"?>
  <ROWS>
    <cfoutput>
      <cfloop from="3" to="#arrayLen(local.array)#" index="local.currentRow" step="1">
        <ROW>
          <cfloop from="1" to="#arrayLen(local.array[2])#" index="local.currentColumn" step="1">
            <#local.array[2][local.currentColumn]#>
              <![CDATA[#trim(local.array[local.currentRow][local.currentColumn])#]]>
            </#local.array[2][local.currentColumn]#>
          </cfloop>
        </ROW>
      </cfloop>
    </cfoutput>
  </ROWS>
</cfsavecontent>
<cfset local.xml = xmlParse(local.xmlString)>
person Beginner    schedule 26.03.2015