Bug 440032 - Share DiagramMappingsManager's computations for several diagrams
Summary: Share DiagramMappingsManager's computations for several diagrams
Status: NEW
Alias: None
Product: Sirius
Classification: Modeling
Component: Diagram (show other bugs)
Version: 1.0.0   Edit
Hardware: PC Linux
: P3 enhancement (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords: performance, triaged
Depends on:
Blocks:
 
Reported: 2014-07-21 12:23 EDT by Cedric Brun CLA
Modified: 2018-12-18 03:43 EST (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Cedric Brun CLA 2014-07-21 12:23:55 EDT
DiagramMappingsManagerImpl is responsible for computing and maintaining a hiearchy of Mappings depending on the layers which are activated.

Right now the code creates a manager for each DDiagram instance, but conceptually two diagrams from the same diagram description with the same list of activated layer will have the same hiearchy table.

We should investigate how to make sure we won't do the same computations twices in those cases.

This part of the code is also very difficult to debug because the relationships between DiagramMappingManagers and DiagramDescriptionMappingManagers are bidirectionals and their lifecycle is not explicit. It might be a good occasion to clear that up a bit...
Comment 1 Cedric Brun CLA 2014-07-30 12:39:11 EDT
Just to document before leaving for vacations.

So far it appears :

DiagramMappingManager & co are eating a lot of memory when one use quite a lot of diagrams (1000s)
Big memory leaks are very easy to get as these instances have a reference to DDiagram instances.
A test case based on EcoreTools 2 with 500K model elements and 2000 diagrams will fail with an OutOfMemorry error when enabling a Viewpoint with the current code, even with 2Go allocated to this.

The logic to "maintain" these instances state up to date is very complex (and I would say quite un-predictable, hard to debug or change in any way).

These instances are listening to the ViewpointRegistry, to the SessionManager just to invalidate some computations and will recompute as soon as there is an update from them (even if we might not need it)

Analysing the actual behavior of these classes and why they are used, their names are badly reflecting what they actually does.

DiagramMappingsManagerRegistry => is actually a cache maintaining all the instances of DiagramMappingsManager and re-trigger their computation on when a session changes. Or when a new layer has been enabled. Or...

DiagramDescriptionMappingsRegistry => a cache of DiagramDescriptionMappingsManager which also re-trigger their computation when the ViewpointRegistry changes. 

DiagramDescriptionMappingsManager => is the result of a computation representing all the mappings (Node/Edge/..) and their hiearchy which are available for a given set of enabled Viewpoints

DiagramMappingsManager => is the result of a computation representing all the available mappings (Node/Edge/...) and their hiearchy which are available from a given set of activated layers. To compute / update its state, the DiagramMappingsManager needs a DiagramDescriptionMappingsManager

DiagramMappingsManagerImpl => is an interesting case of code which scream "I am two implementations in a single class which will change its behavior depending on whether you are in "layer mode" or not".

DiagramDescriptionMappingsManagerListener => exists so that the DiagramMappingsManager will know when the computation result it was based on has changed so that it can trigger its own re-computation.

Preliminary analysis work has been done in this branch: 

https://github.com/cbrun/org.eclipse.sirius/tree/wip/cbr/440032_diagrammappingmanagers (which is not quite ready to be considered for inclusion.)

I took an approach where DiagramMappingManager & DiagramDescriptionMappingsManager are not considered as self-updating themselves anymore and the so-called Registries will either return a cached version or recompute a new one when some client code ask for it.

I choose a very simple eviction strategy : when a Viewpoint is getting enabled/disabled or when a session closes : drop everything. Once the computation is shared among diagram instances through the cache it is not a big deal to have to re-compute the hierarchy of Mappings compared to risking having stalled information or leaks.

With this approach any code keeping a DiagramMappingManager instance as a field is probably wrong as the validity of such a computation is quite short lived. 
Instead it should refers to the Cache and ask for the computation when needed.

I also renamed all those classes to be consistent with the approach.

In its current state the branch gives good performance enhancements, when enabling/disabling a viewpoint, enabling/disabling a layer with several representations having the same combination of activated layers. Impact on the refresh operations themsevles remains to be measured.
Comment 2 Cedric Brun CLA 2014-08-27 11:13:40 EDT
Renaming the Classes in the middle of the work was probably a bad idea as it would make testing more difficult because of the API changes and reviewing would have been harder to.
I pushed here https://github.com/cbrun/org.eclipse.sirius/tree/perfosprint_diagrammappingmanager_440032 a new branch which contains the changes without the renaming.
It is rebased on the "performances" branch so that we can compare the results with the other performance related work.
It is not ready for review yet.