Bug 255534

Summary: Optimize startup performance by replacing EventListenerList implementation
Product: [Tools] GEF Reporter: Iwan Birrer <iwanbirrer>
Component: GEF-Legacy Draw2dAssignee: Anthony Hunter <ahunter.eclipse>
Status: NEW --- QA Contact:
Severity: normal    
Priority: P3 CC: ahunter.eclipse, hudsonr, igor.burilo, tfletche
Version: 3.4   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:
Attachments:
Description Flags
Replacement for the draw2d EventListenerList
none
Executable gef snippet to profile initialization times
none
add profiling screenshot none

Description Iwan Birrer CLA 2008-11-17 11:28:09 EST
Created attachment 118060 [details]
Replacement for the draw2d EventListenerList

Build ID: M20080911-1700

Steps To Reproduce:

1. Create a new Pluin project, add the dependencies listed below to the Manifest and copy the attached EventListenerPerformance.java to the src folder.

- org.eclipse.jface 3.4.0
- org.eclipse.gef 3.4.1
- org.eclipse.core.runtime 3.4.0
- com.ibm.icu 3.8.1 

2. Run the EventListenerPerformance.java. Initialization times are printed to the console.

3. Import the org.eclipse.draw2d plug-in as a source project and replace the org.eclipse.draw2d.EventListenerList with the one in the attachenent.

4. Re-run the EventListenerPerformance.java. Initialization times are printed to the console.


More information:
With a growing number of edit parts (> 5000) the initialization time of a gef editor can increase to several seconds.

After some profiling we found that a great deal of the time is taken by the org.eclipse.draw2d.EventListenerList.addListener() class due to a System.arraycopy() for each listener added to the list.

The attached snippets demonstrates the slow down caused by the EventListenerList class for a growing number of edit parts by measuring the time for EditorViewer.setContents().

2000 edit parts:   141 ms
10000 edit parts:  1828 ms
20000 edit parts:  7109 ms
40000 edit parts: 31235 ms

By removing the array copy in the EventListenerList (see attached EventListenerList.java) and replacing the internal array with a map, we got the following numbers:

2000 edit parts:  110 ms
10000 edit parts:  375 ms
20000 edit parts:  594 ms
40000 edit parts: 1297 ms

The performance gain is quite obvious.
It boils down to a different approach on the array copy strategy: The attached EventListenerList implementation does the copy of the array when iterating over the list while the draw2d/GEF version performs the copy operation when adding a listener to the list. However the attached version may slow down updating the edit parts/figures. Our tests with and editable editor hasn't shown a perceivable slow down though.

We hope somebody can look at this issue and let us know if there's a chance that the EventListenerList implementation is changed for the next release.


Test environment: 
- Intel Core 2, T7200 @ 2 GHz, 2 GB Ram
- JavaSE-1.6
Comment 1 Iwan Birrer CLA 2008-11-17 11:29:36 EST
Created attachment 118061 [details]
Executable gef snippet to profile initialization times
Comment 2 Anthony Hunter CLA 2009-01-23 16:27:12 EST
We need to look into this for 3.5 if a performance gain is to be had.
Comment 3 Randy Hudson CLA 2009-01-26 09:32:56 EST
The implementation of EventListenerList is similar in performance to the implementation of EventTable in SWT, or ListenerList in org.eclipse.core.runtime.  Insertion performance is O(n^2).

With the patch, it is still O(n^2), but the performance for each type of listener interface is isolated from the others.

A better approach would be to grow Object array's size geometrically, as is done in ArrayList#ensureCapacity().  That way the number of calls to arrayCopy is Log(n) instead of N.
Comment 4 Igor Burilo CLA 2010-02-18 05:12:14 EST
I have the same problem too.
For 87000 edit parts it takes about 80 seconds. Also the problem isn't only in EventListenerList but in Figure.addPropertyChangeListener, I'll add an attachment of my profiling.

Target milestone for this bug is set to 3.5, but 3.5 is already completed, is there any plans for this bug for 3.6?
I'm using GEF 3.4.1.
Comment 5 Igor Burilo CLA 2010-02-18 05:13:01 EST
Created attachment 159408 [details]
add profiling screenshot
Comment 6 Alexander Nyßen CLA 2013-10-17 09:45:17 EDT
Unset target milestone as the specified one is already passed.