[announce] InhiBeans: mitigate redundant recalculations

Tomas Mikula tomas.mikula at gmail.com
Thu Jan 16 03:21:05 PST 2014

Hi Alexander,

On Thu, Jan 16, 2014 at 10:24 AM, Alexander Kouznetsov <
alexander.kouznetsov at oracle.com> wrote:

> There are two other options you may want to consider:
> 1) Use XXXBinding as following:
> value.bind(new DoubleBinding() {
> { bind(widthProperty(), heightProperty()); }
> @Override
>                 protected Double computeValue() {
>                     return widthProperty().get() * heightProperty().get();
>                 }
> }
> this will perform the same invalidation mechanics for you as long as your
> value is not requested immediately after change. JavaFX is mostly lazy so
> if you, for example, bind it to some node's property it will be calculated
> only once.

in the past I tried binding Label.textProperty() to a value like this and
it was calculated twice.

> 2) Use AnimationTimer. Its body is always invoked once per pulse so you
> can do as much calculations you need once per pulse.

As I mentioned before, this only works when the result is not observable by
the client code. Otherwise it might be reasonable to assert the following:

 assert obj.getArea() == w*h;

which is not true if area is only calculated on the next pulse.

Moreover, this approach doesn't scale. If you use the trick with next pulse
or runLater in several places in your code and then chain (bind) them, it
will take several pulses to propagate the change. Ironically, it then
doesn't even avoid multiple recalculations (e.g. analyze the case where
these parts depend on each other the way fibonacci numbers do: f[n+2] :=
f[n] + f[n+1]).


> Best regards,
> Alexander Kouznetsov
> (408) 276-0387
> On 15 дек 2013 23:30, John Hendrikx wrote:
>> Since you are only allowed to modify properties on the JavaFX thread (in
>> most cases), I've been using Platform.runLater() to make sure I observe
>> only complete changes.
>> Basically I register an InvalidationListener on the properties that are
>> relevant, and when one gets triggered I set a boolean and trigger a
>> Runnable that
>> will be run on the JavaFX thread later (and after the change completes).
>>  The Runnable checks the relevant values and acts on them, then resets the
>> boolean.
>> I use this mechanism for example when I'm observing Objects with many
>> properties that need to be stored in a database.  To make sure I only store
>> consistent objects, I only observe the values of the properties when my own
>> little piece of observer code runs on the JavaFX thread.  Since nothing can
>> modify the properties except on the JavaFX thread, this is almost like a
>> form of transactions, ensuring that every change has completed before
>> observing the results.
>> --John
>> On 15/12/2013 18:39, Scott Palmer wrote:
>>> Interesting idea.
>>> There is a case I have been curious about and wonder what the best
>>> practices are for it.  Suppose you have a case when you are changing
>>> multiple different properties that will be used in a single calculation.
>>>   You want to deal with a single change to all of them in one go.  E.g.
>>> imagine you have an "area" property that is bound to both "width" and
>>> "height".  You want to write code like:
>>> obj.setWidth(w);
>>> obj.setHeight(h);
>>> and have only ONE recalculation of the area property happen. Currently
>>> the
>>> way bindings work the area will be calculated twice.  The intermediate
>>> calculation is really not a value that you ever want to observe.
>>> Are there helpers for this sort of situation?  Are there guidelines in
>>> the
>>> JavaFX docs somewhere?
>>> Regards,
>>> Scott
>>> On Sat, Dec 14, 2013 at 11:54 PM, Tomas Mikula<tomas.mikula at gmail.com>
>>> wrote:
>>>  Hello,
>>>> I just published a small extension of javafx bindings and properties
>>>> that can help you reduce redundant recalculations.
>>>> They provide two additional methods:
>>>> public void block();
>>>> public void release();
>>>> Call p.block() when you suspect your actions will lead to multiple
>>>> invalidations of p, and call p.release() when you are done and want to
>>>> deliver a single invalidation notification to p's observers.
>>>> https://github.com/TomasMikula/InhiBeans
>>>> Regards,
>>>> Tomas

More information about the openjfx-dev mailing list