Details

    • Type: Improvement Improvement
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Complete
    • Affects Version/s: None
    • Fix Version/s: 2.3.1
    • Security Level: Public (Public: Anyone can view)
    • Labels:
      None
    • Similar issues:
      KULRICE-8797Reduce object creation in view lifecycle
      KULRICE-10547Component lifecycle processing task and execution context
      KULRICE-10539retrieveViaAjax delay lifecycle for components implementation
      KULRICE-10538retrieveViaAjax delay lifecycle analysis
      KULRICE-11298Investigate error with component lifecycle
      KULRICE-8798Look into multithreading during the view lifecycle
      KULRICE-7220Look into replacing component update process with full view lifecycle
      KULRICE-9794Reduce template invocations
      KULRICE-9433Reduce size of html response
      KULRICE-10438Analysis for delaying lifecycle row details component before it is needed
    • Epic Link:
    • Rice Module:
      KRAD
    • KRAD Feature Area:
      UIF MVC
    • Sprint:
      2.3.1 Sprint 2
    • KAI Review Status:
      Not Required
    • KTI Review Status:
      Not Required

      Description

      The following method in the validator class makes multiple calls to getComponentsForLifecycle on the same object. Each call instantiates a large number of objects (due to the way that method is implemented). So minimizing the number of calls is very beneficial

      src/main/java/org/kuali/rice/krad/datadictionary/validator/Validator.java
      private void runValidationsOnLifecycle(Component component, ValidationTrace tracer)

      The below is a different implementation for that method which saves the result for each successive utilization.

      private void runValidationsOnLifecycle(Component component, ValidationTrace tracer) {
      List<Component> componentsForLifecycle = component.getComponentsForLifecycle();
      if (componentsForLifecycle == null)

      { return; }
      if (!doValidationOnUIFBean(component)) { return; }

      tracer.addBean(component);
      for (int j = 0; j < componentsForLifecycle.size(); j++) {
      Component temp = componentsForLifecycle.get(j);
      if (temp == null)

      { continue; }

      if (tracer.getValidationStage() == ValidationTrace.START_UP)

      { ExpressionUtils.populatePropertyExpressionsFromGraph(temp, false); }

      if (temp.isRender())

      { temp.completeValidation(tracer.getCopy()); runValidationsOnLifecycle(temp, tracer.getCopy()); }

      }
      }

        Issue Links

          Activity

          Hide
          Mark Fyffe (Inactive) added a comment -

          Revisited transactional caching of getComponentsForLifecycle()

          When active, some side-effects of this caching became evident. In particular, cached lists don't always include all children at all phases, resulting in missing templates.

          Prior to committing this update, I'll need to correct the error below - I was unable to narrow the root cause down this evening, but once found it appears that reduced object creation is possible through this technique.

          2013-09-09 01:14:05,827 [http-8080-6] u:admin/d: ERROR freemarker.log._Log4JLogg
          erFactory$Log4JLogger - Error executing FreeMarker template
          FreeMarker template error:
          No macro found using uif_messageField
          
          The failing instruction (FTL stack trace):
          ----------
          ==> <#krad_inline "template" />  [in template "krad/WEB-INF/ftl/lib/template.ftl
          " in macro "template" at line 19, column 9]
              @krad.template component=item  [in template "krad/WEB-INF/ftl/dataTablesJson
          .ftl" in macro "uif_table_json" at line 75, column 41]
              @jsonEscape  [in template "krad/WEB-INF/ftl/dataTablesJson.ftl" in macro "ui
          f_table_json" at line 75, column 28]
              @uif_table_json manager, filteredColl...  [in template "krad/WEB-INF/ftl/dat
          aTablesJson.ftl" at line 96, column 5]
              #if KualiForm.updateComponentId??  [in template "krad/WEB-INF/ftl/dataTablesJson.ftl" at line 23, column 1]
              #include "\${KualiForm.requestJsonTem...  [in template "krad/WEB-INF/ftl/uifRender.ftl" at line 41, column 9]
              #if KualiForm.jsonRequest  [in template "krad/WEB-INF/ftl/uifRender.ftl" at line 40, column 5]
          ----------
          
          Java stack trace (for programmers):
          ----------
          freemarker.template.TemplateException: [... Exception message was already printed; see it above ...]
                  at org.kuali.rice.krad.uif.freemarker.FreeMarkerInlineRenderUtils.renderTemplate(FreeMarkerInlineRenderUtils.java:183)
                  at org.kuali.rice.krad.uif.freemarker.FreeMarkerTemplateAdaptor.accept(FreeMarkerTemplateAdaptor.java:57)
                  at freemarker.core.InlineKradElement.accept(InlineKradElement.java:122)
                  at freemarker.core.Environment.visit(Environment.java:265)
                  at freemarker.core.Macro$Context.runMacro(Macro.java:209)
                  at freemarker.core.Environment.visit(Environment.java:694)
                  at freemarker.core.UnifiedCall.accept(UnifiedCall.java:116)
                  at freemarker.core.Environment.visit(Environment.java:265)
                  at freemarker.core.Environment$1.render(Environment.java:313)
                  at org.kuali.rice.krad.uif.freemarker.JsonStringEscapeDirective.execute(JsonStringEscapeDirective.java:67)
                  at freemarker.core.Environment.visit(Environment.java:341)
                  at freemarker.core.UnifiedCall.accept(UnifiedCall.java:136)
                  at freemarker.core.Environment.visit(Environment.java:265)
                  at freemarker.core.MixedContent.accept(MixedContent.java:93)
                  at freemarker.core.Environment.visitByHiddingParent(Environment.java:286)
                  at freemarker.core.IteratorBlock$Context.runLoop(IteratorBlock.java:193)
                  at freemarker.core.Environment.visitIteratorBlock(Environment.java:509)
                  at freemarker.core.IteratorBlock.accept(IteratorBlock.java:103)
                  at freemarker.core.Environment.visit(Environment.java:265)
                  at freemarker.core.MixedContent.accept(MixedContent.java:93)
                  at freemarker.core.Environment.visitByHiddingParent(Environment.java:286)
                  at freemarker.core.Environment.visitAndTransform(Environment.java:377)
                  at freemarker.core.CompressedBlock.accept(CompressedBlock.java:73)
                  at freemarker.core.Environment.visit(Environment.java:265)
                  at freemarker.core.Macro$Context.runMacro(Macro.java:209)
                  at freemarker.core.Environment.visit(Environment.java:694)
                  at freemarker.core.UnifiedCall.accept(UnifiedCall.java:116)
                  at freemarker.core.Environment.visit(Environment.java:265)
                  at freemarker.core.MixedContent.accept(MixedContent.java:93)
                  at freemarker.core.Environment.visit(Environment.java:265)
                  at freemarker.core.IfBlock.accept(IfBlock.java:84)
                  at freemarker.core.Environment.visit(Environment.java:265)
                  at freemarker.core.MixedContent.accept(MixedContent.java:93)
                  at freemarker.core.Environment.visit(Environment.java:265)
                  at freemarker.core.Environment.include(Environment.java:1712)
                  at freemarker.core.Include.accept(Include.java:172)
                  at freemarker.core.Environment.visit(Environment.java:265)
                  at freemarker.core.IfBlock.accept(IfBlock.java:84)
                  at freemarker.core.Environment.visit(Environment.java:265)
                  at freemarker.core.MixedContent.accept(MixedContent.java:93)
                  at freemarker.core.Environment.visitByHiddingParent(Environment.java:286)
                  at freemarker.core.Environment.visitAndTransform(Environment.java:377)
                  at freemarker.core.CompressedBlock.accept(CompressedBlock.java:73)
                  at freemarker.core.Environment.visit(Environment.java:265)
                  at freemarker.core.MixedContent.accept(MixedContent.java:93)
                  at freemarker.core.Environment.visit(Environment.java:265)
                  at freemarker.core.Environment.process(Environment.java:243)
                  at freemarker.template.Template.process(Template.java:277)
                  at org.springframework.web.servlet.view.freemarker.FreeMarkerView.processTemplate(FreeMarkerView.java:366)
                  at org.springframework.web.servlet.view.freemarker.FreeMarkerView.doRender(FreeMarkerView.java:283)
                  at org.springframework.web.servlet.view.freemarker.FreeMarkerView.renderMergedTemplateModel(FreeMarkerView.java:233)
                  at org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:167)
                  at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:263)
                  at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1208)
                  at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:992)
                  at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:939)
                  at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
                  at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
                  at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
                  at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
                  at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
                  at javax.servlet.http.HttpServlet.service(HttpServlet.java:723)
                  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
                  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                  at org.kuali.rice.krad.web.filter.CharsetFilter.doFilter(CharsetFilter.java:58)
                  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                  at org.kuali.rice.krad.web.filter.UserLoginFilter.doFilter(UserLoginFilter.java:89)
                  at org.kuali.rice.krad.web.filter.UserLoginFilter.doFilter(UserLoginFilter.java:77)
                  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                  at org.kuali.rice.krad.web.filter.BootstrapFilterChain.doFilter(BootstrapFilter.java:327)
                  at org.kuali.rice.krad.web.filter.DummyLoginFilter.doFilter(DummyLoginFilter.java:82)
                  at org.kuali.rice.krad.web.filter.DummyLoginFilter.doFilter(DummyLoginFilter.java:62)
                  at org.kuali.rice.krad.web.filter.BootstrapFilterChain.doFilter(BootstrapFilter.java:320)
                  at org.kuali.rice.krad.web.filter.BootstrapFilter.doFilter(BootstrapFilter.java:199)
                  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                  at org.kuali.rice.krad.web.filter.UifSessionTimeoutFilter.doFilter(UifSessionTimeoutFilter.java:106)
                  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                  at org.kuali.rice.core.web.Log4JContextClearingFilter.doFilterInternal(Log4JContextClearingFilter.java:37)
                  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
                  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                  at org.kuali.rice.krad.web.filter.HideWebInfFilter.doFilter(HideWebInfFilter.java:68)
                  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                  at org.springframework.web.filter.AbstractRequestLoggingFilter.doFilterInternal(AbstractRequestLoggingFilter.java:213)
                  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
                  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                  at org.kuali.rice.krad.uif.util.ProcessLoggingFilter$1.call(ProcessLoggingFilter.java:72)
                  at org.kuali.rice.krad.uif.util.ProcessLoggingFilter$1.call(ProcessLoggingFilter.java:69)
                  at org.kuali.rice.krad.uif.util.ProcessLogger.follow(ProcessLogger.java:645)
                  at org.kuali.rice.krad.uif.util.ProcessLoggingFilter.doFilter(ProcessLoggingFilter.java:69)
                  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                  at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
                  at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
                  at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
                  at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
                  at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
                  at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
                  at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
                  at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)
                  at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
                  at java.lang.Thread.run(Thread.java:724)
          
          Show
          Mark Fyffe (Inactive) added a comment - Revisited transactional caching of getComponentsForLifecycle() When active, some side-effects of this caching became evident. In particular, cached lists don't always include all children at all phases, resulting in missing templates. Prior to committing this update, I'll need to correct the error below - I was unable to narrow the root cause down this evening, but once found it appears that reduced object creation is possible through this technique. 2013-09-09 01:14:05,827 [http-8080-6] u:admin/d: ERROR freemarker.log._Log4JLogg erFactory$Log4JLogger - Error executing FreeMarker template FreeMarker template error: No macro found using uif_messageField The failing instruction (FTL stack trace): ---------- ==> <#krad_inline "template" /> [in template "krad/WEB-INF/ftl/lib/template.ftl " in macro "template" at line 19, column 9] @krad.template component=item [in template "krad/WEB-INF/ftl/dataTablesJson .ftl" in macro "uif_table_json" at line 75, column 41] @jsonEscape [in template "krad/WEB-INF/ftl/dataTablesJson.ftl" in macro "ui f_table_json" at line 75, column 28] @uif_table_json manager, filteredColl... [in template "krad/WEB-INF/ftl/dat aTablesJson.ftl" at line 96, column 5] #if KualiForm.updateComponentId?? [in template "krad/WEB-INF/ftl/dataTablesJson.ftl" at line 23, column 1] #include "\${KualiForm.requestJsonTem... [in template "krad/WEB-INF/ftl/uifRender.ftl" at line 41, column 9] #if KualiForm.jsonRequest [in template "krad/WEB-INF/ftl/uifRender.ftl" at line 40, column 5] ---------- Java stack trace (for programmers): ---------- freemarker.template.TemplateException: [... Exception message was already printed; see it above ...] at org.kuali.rice.krad.uif.freemarker.FreeMarkerInlineRenderUtils.renderTemplate(FreeMarkerInlineRenderUtils.java:183) at org.kuali.rice.krad.uif.freemarker.FreeMarkerTemplateAdaptor.accept(FreeMarkerTemplateAdaptor.java:57) at freemarker.core.InlineKradElement.accept(InlineKradElement.java:122) at freemarker.core.Environment.visit(Environment.java:265) at freemarker.core.Macro$Context.runMacro(Macro.java:209) at freemarker.core.Environment.visit(Environment.java:694) at freemarker.core.UnifiedCall.accept(UnifiedCall.java:116) at freemarker.core.Environment.visit(Environment.java:265) at freemarker.core.Environment$1.render(Environment.java:313) at org.kuali.rice.krad.uif.freemarker.JsonStringEscapeDirective.execute(JsonStringEscapeDirective.java:67) at freemarker.core.Environment.visit(Environment.java:341) at freemarker.core.UnifiedCall.accept(UnifiedCall.java:136) at freemarker.core.Environment.visit(Environment.java:265) at freemarker.core.MixedContent.accept(MixedContent.java:93) at freemarker.core.Environment.visitByHiddingParent(Environment.java:286) at freemarker.core.IteratorBlock$Context.runLoop(IteratorBlock.java:193) at freemarker.core.Environment.visitIteratorBlock(Environment.java:509) at freemarker.core.IteratorBlock.accept(IteratorBlock.java:103) at freemarker.core.Environment.visit(Environment.java:265) at freemarker.core.MixedContent.accept(MixedContent.java:93) at freemarker.core.Environment.visitByHiddingParent(Environment.java:286) at freemarker.core.Environment.visitAndTransform(Environment.java:377) at freemarker.core.CompressedBlock.accept(CompressedBlock.java:73) at freemarker.core.Environment.visit(Environment.java:265) at freemarker.core.Macro$Context.runMacro(Macro.java:209) at freemarker.core.Environment.visit(Environment.java:694) at freemarker.core.UnifiedCall.accept(UnifiedCall.java:116) at freemarker.core.Environment.visit(Environment.java:265) at freemarker.core.MixedContent.accept(MixedContent.java:93) at freemarker.core.Environment.visit(Environment.java:265) at freemarker.core.IfBlock.accept(IfBlock.java:84) at freemarker.core.Environment.visit(Environment.java:265) at freemarker.core.MixedContent.accept(MixedContent.java:93) at freemarker.core.Environment.visit(Environment.java:265) at freemarker.core.Environment.include(Environment.java:1712) at freemarker.core.Include.accept(Include.java:172) at freemarker.core.Environment.visit(Environment.java:265) at freemarker.core.IfBlock.accept(IfBlock.java:84) at freemarker.core.Environment.visit(Environment.java:265) at freemarker.core.MixedContent.accept(MixedContent.java:93) at freemarker.core.Environment.visitByHiddingParent(Environment.java:286) at freemarker.core.Environment.visitAndTransform(Environment.java:377) at freemarker.core.CompressedBlock.accept(CompressedBlock.java:73) at freemarker.core.Environment.visit(Environment.java:265) at freemarker.core.MixedContent.accept(MixedContent.java:93) at freemarker.core.Environment.visit(Environment.java:265) at freemarker.core.Environment.process(Environment.java:243) at freemarker.template.Template.process(Template.java:277) at org.springframework.web.servlet.view.freemarker.FreeMarkerView.processTemplate(FreeMarkerView.java:366) at org.springframework.web.servlet.view.freemarker.FreeMarkerView.doRender(FreeMarkerView.java:283) at org.springframework.web.servlet.view.freemarker.FreeMarkerView.renderMergedTemplateModel(FreeMarkerView.java:233) at org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:167) at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:263) at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1208) at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:992) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:939) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827) at javax.servlet.http.HttpServlet.service(HttpServlet.java:617) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812) at javax.servlet.http.HttpServlet.service(HttpServlet.java:723) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.kuali.rice.krad.web.filter.CharsetFilter.doFilter(CharsetFilter.java:58) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.kuali.rice.krad.web.filter.UserLoginFilter.doFilter(UserLoginFilter.java:89) at org.kuali.rice.krad.web.filter.UserLoginFilter.doFilter(UserLoginFilter.java:77) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.kuali.rice.krad.web.filter.BootstrapFilterChain.doFilter(BootstrapFilter.java:327) at org.kuali.rice.krad.web.filter.DummyLoginFilter.doFilter(DummyLoginFilter.java:82) at org.kuali.rice.krad.web.filter.DummyLoginFilter.doFilter(DummyLoginFilter.java:62) at org.kuali.rice.krad.web.filter.BootstrapFilterChain.doFilter(BootstrapFilter.java:320) at org.kuali.rice.krad.web.filter.BootstrapFilter.doFilter(BootstrapFilter.java:199) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.kuali.rice.krad.web.filter.UifSessionTimeoutFilter.doFilter(UifSessionTimeoutFilter.java:106) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.kuali.rice.core.web.Log4JContextClearingFilter.doFilterInternal(Log4JContextClearingFilter.java:37) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.kuali.rice.krad.web.filter.HideWebInfFilter.doFilter(HideWebInfFilter.java:68) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.springframework.web.filter.AbstractRequestLoggingFilter.doFilterInternal(AbstractRequestLoggingFilter.java:213) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.kuali.rice.krad.uif.util.ProcessLoggingFilter$1.call(ProcessLoggingFilter.java:72) at org.kuali.rice.krad.uif.util.ProcessLoggingFilter$1.call(ProcessLoggingFilter.java:69) at org.kuali.rice.krad.uif.util.ProcessLogger.follow(ProcessLogger.java:645) at org.kuali.rice.krad.uif.util.ProcessLoggingFilter.doFilter(ProcessLoggingFilter.java:69) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489) at java.lang.Thread.run(Thread.java:724)
          Hide
          Mark Fyffe (Inactive) added a comment -

          Attached patch file of transactional list caching effort indicated in comments on this issue. So far, this technique is leading to rendering errors so I can't commit these changes just yet.

          Show
          Mark Fyffe (Inactive) added a comment - Attached patch file of transactional list caching effort indicated in comments on this issue. So far, this technique is leading to rendering errors so I can't commit these changes just yet.
          Hide
          Mark Fyffe (Inactive) added a comment -

          Backed out caching of nested component lists after testing led to a variety of rendering errors. Significant reductions on object creation for large views are possible using this technique, but a thorough review of components will be needed in order to allow cached transaction lists to follow impacting changes. I tried a few different approaches, but the second pass at reducing object creation yielded either no benefits or rendering errors so related changes have been deferred for later efforts.

          In a third pass at reducing object creation, I have reduced calls to getComponentsForLifecycle() by reusing component lists for specific scenarios:

          • Validator.runValidationsOnLifecycle() - as originally reported the getComponentsForLifecycle() call was repeated several times, including as the limit condition in a for() loop. When used on a deep component, this loop could becoime very heavy.
          • Updated pushAllToContext() to minimize traversal of property replacers
          • Refactored several methods in ComponentUtils to eliminate creation of empty ArrayList insteances, reduce nested component traversal overhead through tail-recursion, and maximize the effectiveness of each traversal when appropriate:
            • Short circuit to return Collections.emptyList() when passed an empty list:
              • copyFieldList
              • copyComponentList
              • getComponentsOfType
              • getComponentsofTypeShallow
              • getComponentsofTypeDeep
              • getNestedComponentsofTypeShallow
              • getAllNestedComponents
            • Delay creation of ArrayList until first object is added:
              • getComponentsOfType
              • getComponentsOfTypeShallow
              • getComponentsOfTypeDeep
              • getNestedComponentsofTypeShallow
              • getAllNestedComponents
            • Use tail-recursion to minimize ArrayList creation while traversing deep lists
              • getComponentsOfTypeDeep
              • getAllNestedComponents
              • findNestedComponentById
              • pushObjectToContext
            • Eliminate calls to build list for traversal by traversing directly
              • findNestedComponentById
            • Added method pushAllToContext() for adding all map entries to nested components with a single traversal.
              • Changed updateContextForLine to use pushAllToContext() instead of multiple calls to pushObjectToContext()
            • Converted sort loops to use foreach() form instead of index counter.

          Additional reductions included in the third pass:

          • Converted Group and CollectionGroup initial lists to use Collections.emptyList() instead of new ArrayList(). Since the initial list is never modified, this solution reduces object creation without adding the risk of introducing NPE errors.
          • Eliminated initial cssClasses and propertyReplacer lists from LayoutManagerBase, checked for NPE conditions.
          • Added isEmpty() checks after null checks in copy() method in ComponentBase, Group, CollectionGroup, and LayoutManagerBase to skip creation of ArrayList when the source list is already empty.
          • Converted getContext() calls to return an unmodifiable map, and initialized the context map to Collections.emptyMap(). This enforces the intended usage of the context map to ensure that operations on the context may be optimized with ComponentBase and LayoutManagerBase without side-effects. Added pushAllToContext() to LayoutManager interface, and corrected external modification of the context from ViewHelperServiceImpl to use this method instead.
          Show
          Mark Fyffe (Inactive) added a comment - Backed out caching of nested component lists after testing led to a variety of rendering errors. Significant reductions on object creation for large views are possible using this technique, but a thorough review of components will be needed in order to allow cached transaction lists to follow impacting changes. I tried a few different approaches, but the second pass at reducing object creation yielded either no benefits or rendering errors so related changes have been deferred for later efforts. In a third pass at reducing object creation, I have reduced calls to getComponentsForLifecycle() by reusing component lists for specific scenarios: Validator.runValidationsOnLifecycle() - as originally reported the getComponentsForLifecycle() call was repeated several times, including as the limit condition in a for() loop. When used on a deep component, this loop could becoime very heavy. Updated pushAllToContext() to minimize traversal of property replacers Refactored several methods in ComponentUtils to eliminate creation of empty ArrayList insteances, reduce nested component traversal overhead through tail-recursion, and maximize the effectiveness of each traversal when appropriate: Short circuit to return Collections.emptyList() when passed an empty list: copyFieldList copyComponentList getComponentsOfType getComponentsofTypeShallow getComponentsofTypeDeep getNestedComponentsofTypeShallow getAllNestedComponents Delay creation of ArrayList until first object is added: getComponentsOfType getComponentsOfTypeShallow getComponentsOfTypeDeep getNestedComponentsofTypeShallow getAllNestedComponents Use tail-recursion to minimize ArrayList creation while traversing deep lists getComponentsOfTypeDeep getAllNestedComponents findNestedComponentById pushObjectToContext Eliminate calls to build list for traversal by traversing directly findNestedComponentById Added method pushAllToContext() for adding all map entries to nested components with a single traversal. Changed updateContextForLine to use pushAllToContext() instead of multiple calls to pushObjectToContext() Converted sort loops to use foreach() form instead of index counter. Additional reductions included in the third pass: Converted Group and CollectionGroup initial lists to use Collections.emptyList() instead of new ArrayList(). Since the initial list is never modified, this solution reduces object creation without adding the risk of introducing NPE errors. Eliminated initial cssClasses and propertyReplacer lists from LayoutManagerBase, checked for NPE conditions. Added isEmpty() checks after null checks in copy() method in ComponentBase, Group, CollectionGroup, and LayoutManagerBase to skip creation of ArrayList when the source list is already empty. Converted getContext() calls to return an unmodifiable map, and initialized the context map to Collections.emptyMap(). This enforces the intended usage of the context map to ensure that operations on the context may be optimized with ComponentBase and LayoutManagerBase without side-effects. Added pushAllToContext() to LayoutManager interface, and corrected external modification of the context from ViewHelperServiceImpl to use this method instead.
          Hide
          Mark Fyffe (Inactive) added a comment -

          Resolving issue.

          Add code review https://fisheye.kuali.org/cru/rice-288

          Show
          Mark Fyffe (Inactive) added a comment - Resolving issue. Add code review https://fisheye.kuali.org/cru/rice-288
          Hide
          Mark Fyffe (Inactive) added a comment -

          KULRICE-8797 has similar focus and some analysis performed already by Eric Westfal. Similar to Eric's findings, caching component lists and resuing components is not workable in the current state of UIF.

          Show
          Mark Fyffe (Inactive) added a comment - KULRICE-8797 has similar focus and some analysis performed already by Eric Westfal. Similar to Eric's findings, caching component lists and resuing components is not workable in the current state of UIF.

            People

            • Assignee:
              Mark Fyffe (Inactive)
              Reporter:
              Jeff Domeyer (Inactive)
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Time Tracking

                Estimated:
                Original Estimate - 1 day, 2 hours Original Estimate - 1 day, 2 hours
                1d 2h
                Remaining:
                Remaining Estimate - 0 minutes
                0m
                Logged:
                Time Spent - 1 day, 3 hours
                1d 3h

                  Agile

                    Structure Helper Panel