On Mon, 5 Apr 2021 21:54:40 GMT, Kevin Rushforth <k...@openjdk.org> wrote:
>> The internal BidirectionalBinding class implements bidirectional bindings >> for JavaFX properties. The design intent of this class is to provide >> specializations for primitive value types to prevent boxing conversions (cf. >> specializations of the Property class with a similar design intent). >> >> However, the primitive BidirectionalBinding implementations do not meet the >> design goal of preventing boxing conversions, because they implement >> ChangeListener. >> >> ChangeListener is a generic SAM interface, which makes it impossibe to >> invoke an implementation of ChangeListener::changed with a primitive value >> (i.e. any primitive value will be auto-boxed). >> >> The boxing conversion happens, as with all ChangeListeners, at the >> invocation site (for example, in ExpressionHelper). Since the boxing >> conversion has already happened by the time any of the BidirectionalBinding >> implementations is invoked, there's no point in using primitive >> specializations of BidirectionalBinding after the fact. >> >> This issue can be solved by having BidirectionalBinding implement >> InvalidationListener instead, which by itself does not incur a boxing >> conversion. Because bidirectional bindings are eagerly evaluated, the >> observable behavior remains the same. >> >> I've filed a bug report with the same title. > > I don't see this or any similar bug filed in our incident tracker. Did the > submission complete to the point where you have an internal tracking number? > > Is there a measurable benefit in doing this? For example, do you have a > benchmark of some sort that shows garbage generation has been reduced or > performance has been improved? Seems like I forgot to hit the send button on the webform. Here's the tracking number: 9069787. I've used the following manual benchmark, which bidirectionally binds two properties and then produces a billion change notifications. DoubleProperty property1 = new SimpleDoubleProperty(); DoubleProperty property2 = new SimpleDoubleProperty(); property2.bindBidirectional(property1); long start = System.nanoTime(); for (int i = 0; i < 1000000000; ++i) { property1.set((i % 2 == 0) ? 12345.0 : 54321.0); } long end = System.nanoTime(); System.out.println("Time elapsed (ms): " + (end - start) / 1000000); And these are the results I got (time elapsed, in milliseconds): | | before | after | | ------------|--------|-------| | Test run 1: | 28608 | 9122 | | Test run 2: | 27928 | 9065 | | Test run 3: | 31140 | 9181 | | Test run 4: | 28041 | 9127 | | Test run 5: | 28730 | 9181 | So in this synthetic benchmark, the new implementation has a 3x performance improvement compared to the old implementation. ------------- PR: https://git.openjdk.java.net/jfx/pull/454