| Summary: | Optimize performance by centralizing behaviors to the root part. | ||
|---|---|---|---|
| Product: | [Tools] GEF | Reporter: | Matthias Wienand <matthias.wienand> |
| Component: | GEF MVC | Assignee: | gef-inbox <gef-inbox> |
| Status: | RESOLVED FIXED | QA Contact: | |
| Severity: | normal | ||
| Priority: | P3 | CC: | cletavernier, nyssen, peter |
| Version: | unspecified | ||
| Target Milestone: | 5.0.0 (Oxygen) M1 | ||
| Hardware: | All | ||
| OS: | All | ||
| Whiteboard: | |||
|
Description
Matthias Wienand
A major performance issue is that multi selection is performed by delegating to the selection policies of the individually selected parts, whereas the selection could be set as a whole on the selection model. (In reply to Alexander Nyßen from comment #1) > A major performance issue is that multi selection is performed by delegating > to the selection policies of the individually selected parts, whereas the > selection could be set as a whole on the selection model. I have refactored that in terms of bug #450223, gaining a significant performance increase upon marquee selection. What remains is to investigate performance of feedback/handles creation. It seems the major performance drawback is the listener mechanism involved here. Maybe it would be better to centralize selection and hover behavior by binding them only to root part. I created a topic branch for this bug (bug_440958) and centralized the generation of selection feedback and handles in that branch by binding an adjusted SelectionBehavior only for the root part. Based on these changes, we can investigate if the centralization of the generation of feedback and handles has a noticable performance impact. I compared the performance for selection feedback generation in the centralized and distributed cases with the following results:
Number of nodes | Time, centralized | Time, distributed
500 | ca. 1.5s | ca. 1.5s (3 runs avg.)
1000 | ca. 3.5s | ca. 3.5s (6 runs avg.)
3000 | ca. 23.0s | ca. 24.0s (2 runs avg.)
6000 | ca. 105.0s | ca. 110.0s (2 runs avg.)
The application was restarted before every run. When performing the selection multiple times in a row without restarting the application, the performance increases (possibly due to (hot path) optimization within the JVM):
1000 nodes, centralized: 3.4s -> 2.4s -> 2.2s -> 2s -> 1.9s
1000 nodes, distributed: 4.0s -> 2.3s -> 2.0s -> 1.9s
The numbers provide us with two information: 1) centralizing the feedback generation does not produce a performance increase, and 2) feedback generation has an exponential time complexity. Therefore, the performance can possibly be increased significantly if the bottleneck of the algorithm can be found.
I think we should re-evaluate this after the changes we applied to bug #486620. Maybe that has changed something w.r.t. the exponential complexity. If not we need to further investigate this. We reevaluated the centralization of behaviors and found a significant influence on the performance, especially on windows systems. Therefore, we decided to centralize all behaviors that (in-directly) react to input events (hover, selection, and focus) to the root part. Other behaviors, such as the ContentBehavior, are not affected, and therefore, do not need to be centralized. In the context of this bug, we should also clarify the contract between the behaviors and the factories. Per default, the user should have the opportunity to generate feedback and handles individually per target part (selection, hover, focus, etc.), as well as for the whole set of target parts. Therefore, the behaviors should issue different calls to the factories, one for the whole set of targets, and one for each target. The factories can then decide whether or not to generate feedback/handles for the given targets. I centralized the hover, focus, and selection behaviors by binding them only to the root part. Therefore, only one observer per behavior is registered at the viewer models. The new API for adding and removing feedback and handles is provided by AbstractBehavior. Feedback and handles are now maintained, created and added, and removed and disposed for sets of target parts. AbstractBehavior is now responsible for maintaining, creating, adding, removing, and disposing feedback and handle parts. Prior, the individual behavior implementations performed the creation and the disposal of these parts. The old feedback and handles API for behaviors did only allow one list of feedback parts and one list of handle parts per host: - Set stored feedback parts and establish anchorage-anchored relations: addFeedback(List targets, List feedback) - Set stored handle parts and establish anchorage-anchored relations: addHandles(List targets, List handles) - Remove feedback parts and unestablish anchorage-anchored relations: removeFeedback(List targets) - Remove feedback parts and unestablish anchorage-anchored relations: removeHandles(List targets) - Retrieve stored feedback parts: getFeedbackParts() : List - Retrieve stored handle parts: getHandleParts() : List The new feedback and handles API for behaviors allows one list of feedback and handle parts for each set of target parts and the creation, addition, and removal of feedback and handle parts is performed by AbstractBehavior: - Create and add feedback: addFeedback(List targets), addFeedback(IVisualPart target) - Create and add handles: addHandles(List targets), addHandles(IVisualPart target) - Remove and dispose feedback: removeFeedback(Set targets), removeFeedback(Collection targets), removeFeedback(IVisualPart target) - Remove and dispose handles: removeHandles(Set targets), removeHandles(Collection targets), removeHandles(IVisualPart target) - Determine feedback: getFeedback(Collection targets), getFeedback(IVisualPart target) - Determine handles: getHandles(Collection targets), getHandles(IVisualPart target) - Determine if feedback was created (even if no parts were added): hasFeedback(Collection targets), hasFeedback(IVisualPart target) - Determine if handles were created (even if no parts were added): hasHandles(Collection targets), hasHandles(IVisualPart target) A role is required for the determination of the feedback and handle part factories. These roles are determined by AbstractBehavior using the getFeedbackPartFactoryRole() and getHandlePartFactoryRole() methods. The default implementation of these methods throws an UnsupportedOperationException that informs the user of having to implement these methods in order for the default feedback and handles mechanism to work. The code is published on the master branch, therefore, I am resolving this ticket as fixed for 5.0.0 M1. |