Uploaded image for project: 'Kuali Rice Development'
  1. Kuali Rice Development
  2. KULRICE-8954

Reduce object creation in component lifecycle

    Details

    • Type: Improvement
    • Status: Closed
    • Priority: Major
    • Resolution: Complete
    • Affects Version/s: None
    • Fix Version/s: 2.3.1
    • Security Level: Public (Public: Anyone can view)
    • Labels:
      None
    • 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()); }

      }
      }

        Attachments

          Issue Links

            Activity

            Hide
            mwfyffe 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
            mwfyffe 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
            mwfyffe 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
            mwfyffe 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
            mwfyffe 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
            mwfyffe 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
            mwfyffe Mark Fyffe (Inactive) added a comment -

            Resolving issue.

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

            Show
            mwfyffe Mark Fyffe (Inactive) added a comment - Resolving issue. Add code review https://fisheye.kuali.org/cru/rice-288
            Hide
            mwfyffe 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
            mwfyffe 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:
                mwfyffe Mark Fyffe (Inactive)
                Reporter:
                jdomeyer 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