Continuing analysis initially started on
KULRICE-10980 as a solution for this issue. Upon closer inspection of this issue, and more thorough analysis of using proxies to reduce copy overhead, the same proxy sounds like the right approach for addressing this issue. A description of this solution, from a recent email to Jerry, follows:
What I'm thinking about for the last piece of
KULRICE-10980 is to short-circuit copy on nested components that can be represented by an interface, replacing the deep copy with a simple proxy with a reference back to the original (cached) component. The first time the proxy component is used for anything other than to get the value of an atomic bean property not in the expression graph, the original will be copied - the call triggering the copy and all future calls to the proxy will then be sent to the copy component rather than the cached original. In addition to limiting copy(), the proxy should also be useful for facilitating fine-grained reuse of component instances. The main caveat I ran into on my first stab at this approach is that some components (Group, CollectionGroup, DataField, etc) don't have interfaces, but do have explicit casts from Component in several places. I tried to work around this creatively, but quickly recalled that proxies truly prefer interfaces to creative workarounds I decided to back out the workarounds and take a direct approach on the next pass.
So far, I have restored the DelayedCopyHandler implementation from the analysis on
KULRICE-10980, and removed ProxyBean piece. In order to support current lifecycle processing tasks and FreeMarker templates, I've extracted interfaces for the following component and layout manager classes and am working through unit testing:
All of these classes have been renamed so that the interface carries the original class name, and the class has "Base" appended. Spring XML references have been updated. One unit testing and KRAD sampleapp regression testing is passing, I'll commit to the performance branch.
In addition to the interface conversion and implementation of delayed copy proxy, I have added a "pre-process" step to view processing. Pre-processing takes pace on the newly created view directly after retrieval from Spring, and before caching in UifDictionaryIndex. This step currently generates all IDs and initial component states, so lifecycle initialize phase tasks that with results common to all instances of the same view are cached along with the meta-information from Spring. Other common processing tasks can be performed prior to caching as identified to both eliminate expensive lifecycle processing steps, and to limit the need to trigger copying when working with the delayed copy proxy.
After establishing stability for the current phase, the next steps to directly address this issue are:
- Implement the filter on delayed copy to identify calls to property read methods for atomic bean properties not in the expression graph, and suppress copy for those calls.
- Convert PageGroup to an interface following the paradigm used for other classes.
- Confirm that pages are not copied immediately upon retrieving the view from cache, and work to eliminate events that trigger page copying. Since the page is added to the lifecycle via the currentPage property, rather than via items, this should fall into place.
- Cleanup and troubleshooting.