Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve EventListenerList Performance Bugzilla #255534 #607

Merged
merged 2 commits into from
Nov 11, 2024

Conversation

azoitl
Copy link
Contributor

@azoitl azoitl commented Nov 2, 2024

By separating the event listener types into individual lists and using a map the startup performance could be greatly reduced. It is for small number of EditParts (i.e., 2000) already twice as fast as the previous implementation.
Furthermore iterating through the event listeners is simpler and most probably also faster.

The work is based on the patch submitted by Iwan Birrer to the following Bugzilla entry:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=255534

@azoitl azoitl requested a review from ptziegler November 2, 2024 20:42
@azoitl azoitl force-pushed the eventListenersAsMap branch from f25310a to 975f249 Compare November 2, 2024 21:04
@ptziegler
Copy link
Contributor

Do you also want to add the snippet that was attached to the Bugzilla item? I think it would be nice to have an easy way to compare the performance of the different implementations.

@azoitl
Copy link
Contributor Author

azoitl commented Nov 2, 2024

Do you also want to add the snippet that was attached to the Bugzilla item? I think it would be nice to have an easy way to compare the performance of the different implementations.

I was not sure about the legal implications of adding this one.

@ptziegler
Copy link
Contributor

Do you also want to add the snippet that was attached to the Bugzilla item? I think it would be nice to have an easy way to compare the performance of the different implementations.

I was not sure about the legal implications of adding this one.

Fair point. Though I still believe that a controlled test to measure the performance would help out a lot.

@azoitl azoitl force-pushed the eventListenersAsMap branch from 975f249 to 75b10a9 Compare November 2, 2024 22:42
@ptziegler
Copy link
Contributor

Maybe to just summarize the open topics:

  • I'm not a big fan of creating a copy whenever the getters are called, as it feels like it just shifts the startup delay. I'm fine with either an ArrayList or a LinkedList.

  • If a concurrent list is used, we also need to decide how to handle "null" listeners, which are currently supported, even though I don't see a real use case for them...

@azoitl
Copy link
Contributor Author

azoitl commented Nov 5, 2024

Maybe to just summarize the open topics:

* I'm not a big fan of creating a copy whenever the getters are called, as it feels like it just shifts the startup delay. 

me neither.

I'm fine with either an ArrayList or a LinkedList.

I only had concerns that a LinkedList normally uses at least one additional pointer (next) mostly two (next and prev) so we would have a 200% overhead compared to an ArrayList. But as your measurement proved differently I think we could go with the ConcurrentLinkedDeque or did I miss anything?

* If a concurrent list is used, we also need to decide how to handle "null" listeners, which are currently supported, even though I don't see a real use case for them...

I'm not sure if I get you here. You mean removing the map entry if the list is empty? If yes I would do so.

@ptziegler
Copy link
Contributor

I only had concerns that a LinkedList normally uses at least one additional pointer (next) mostly two (next and prev) so we would have a 200% overhead compared to an ArrayList. But as your measurement proved differently I think we could go with the ConcurrentLinkedDeque or did I miss anything?

The linked list is still larger, I only wondered whether that's by a significant margin. At the end of the day, it's your PR so you're free to choose the approach you prefer. ;D

I'm not sure if I get you here. You mean removing the map entry if the list is empty? If yes I would do so.

That's an oversight on my part. I though that you could call addListener(..., null) without error, but I missed the check at the start of the method.

Tough I still believe that removing the map entry when the list of listeners is empty to be a good idea. Even if it just prevents any hard reference to the classes and thus potentially blocking class loaders from being garbage collected. I experienced a similar issues a few months ago with the platform, which made me cautions whenever I see something related to classes.

By separating the event listener types into individual lists and using a
map the startup performance could be greatly reduced. It is for small
number of EditParts (i.e., 2000) already twice as fast as the previous
implementation.
Furthermore iterating through the event listeners is simpler and most
probably also faster.

The work is based on the patch submitted by Iwan Birrer to the following
Bugzilla entry:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=255534
@azoitl azoitl force-pushed the eventListenersAsMap branch from 75b10a9 to 28c8e8b Compare November 10, 2024 14:48
@azoitl
Copy link
Contributor Author

azoitl commented Nov 10, 2024

I did some further reading and and some more experiments. The Deque/ConcurrentLinkedDeque is faster then the CopyOnWriteArrayList. Also when I used this approach in 4diac IDE with larger diagrams and many editors (app. 100 editors with large diagrams) i didn't see a major increase in memory usage. So I would go with the Deque/ConcurrentLinkedDeque approach for now.

Copy link
Contributor

@ptziegler ptziegler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also looking good, outside of a very small optimization.

@azoitl azoitl merged commit 3b334bd into eclipse-gef:master Nov 11, 2024
9 checks passed
@azoitl azoitl deleted the eventListenersAsMap branch November 11, 2024 16:16
@ptziegler
Copy link
Contributor

I did some further reading and and some more experiments. The Deque/ConcurrentLinkedDeque is faster then the CopyOnWriteArrayList. Also when I used this approach in 4diac IDE with larger diagrams and many editors (app. 100 editors with large diagrams) i didn't see a major increase in memory usage. So I would go with the Deque/ConcurrentLinkedDeque approach for now.

That's good to hear! I also apologize for being really picky about this class. 😅 I just always fear that a lot of stuff can easily go wrong with this kind of optimizations.

@azoitl
Copy link
Contributor Author

azoitl commented Nov 11, 2024

I did some further reading and and some more experiments. The Deque/ConcurrentLinkedDeque is faster then the CopyOnWriteArrayList. Also when I used this approach in 4diac IDE with larger diagrams and many editors (app. 100 editors with large diagrams) i didn't see a major increase in memory usage. So I would go with the Deque/ConcurrentLinkedDeque approach for now.

That's good to hear! I also apologize for being really picky about this class. 😅 I just always fear that a lot of stuff can easily go wrong with this kind of optimizations.

I'm very happy that you are here so strict on me. This is a very central class breaking it may have rather large consequences.

@ptziegler ptziegler added this to the 3.22.0 milestone Nov 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants