<div style="font-family: 'verdana'; font-size: 12px; color: #000;"><span style="background-color: #ffffff;">This idea sounds interesting. <br>Unfortunately, I never looked into the numbers, e.g. I have no idea how many listeners plain Nodes, Controls or Charts (with many Data points) have.<br>That would be interesting to better understand the current situation, and how we want to optimize the listener data structure.</span></div>
<div style="font-family: 'verdana'; font-size: 12px; color: #000;"><span style="background-color: #ffffff;"> </span></div>
<div style="font-family: 'verdana'; font-size: 12px; color: #000;"><span style="background-color: #ffffff;">-- Marius</span></div>
<div id="sub-body-container" style="margin: 10px 5px 5px 10px; padding: 10px 0px 10px 10px; border-left: 2px solid rgb(195, 217, 229);">
<div style="margin: 0px 0px 10px;">
<div><strong>Gesendet: </strong>Samstag, 22. November 2025 um 21:35</div>
<div><strong>Von: </strong>"John Hendrikx" <john.hendrikx@gmail.com></div>
<div><strong>An: </strong>OpenJFX <openjfx-dev@openjdk.org></div>
<div><strong>Betreff: </strong>Faster listener removal</div>
</div>
A long time ago there was some discussion on large listener lists, and<br>how they perform very poorly when cleaning up (removing existing listeners).<br><br>A listener list basically needs to support the following operations:<br><br>- append at end, allowing duplicates<br>- remove by value, removing the first (oldest) match only<br>- iteration<br><br>It has no other needs.<br><br>There was some discussion if this could be replaced with a<br>LinkedHashMap, but it handles duplicates subtly different and is not<br>very fast at iteration (lots of random memory accesses).<br><br>So I created what is best described as an "ordered" bag.  It allows<br>adding and removal, while maintaining order and because it is backed by<br>(amongst others) an ordered array, iteration is about as fast as what<br>ArrayList does.  It has O(1) insertion, O(1) removal, O(n) iteration,<br>but about 3x the memory requirements (not including the listener cost<br>itself), unless the list is small (for small lists the overhead is only<br>slightly higher than ArrayList).<br><br>Insertion is about 5x slower than ArrayList; Removal is far faster (150x<br>faster for a 10000 listener case); Iteration is almost equally fast.<br><br>Because it has the exact same semantics as an (Array)List with regards<br>to duplicates and their removal order, it is a drop-in replacement.<br><br>Internally it works by maintaining an ordered array (basically what<br>ArrayList has) which is allowed to have removal gaps that are skipped<br>during iteration.  When the array needs to grow, it first sees if it can<br>consolidate the gaps before increasing the size (and it also shrinks on<br>demand, unlike ArrayList).  Other than that, for lists above a certain<br>size, it maintains three additional arrays; these are used to maintain<br>hashed linked lists of similar elements (basically a singly linked list<br>per bucket, but with fast appends at the end using a tail pointer).<br><br>When the number of listeners is low, the implementation falls back on<br>the simple array only (and the other 3 lists are nulled), which means<br>that for small lists the overhead is minimal.  It's sort of a best of<br>both worlds thing (although there is always overhead), where it uses<br>minimal memory for small lists and simply scans the entire list for<br>removals, while for large lists it initializes additional structures to<br>allow for quick removals at any size.<br><br>Thoughts?<br><br>--John<br><br></div>