Articles related to JavaFX Script Mike's Weblog

Sunday Feb 22, 2009

As everybody who is interested in JavaFX will know by now, JavaFX Mobile was released a short while ago. It was a hell of a ride, that's for sure. I felt so exhausted, I did not even have the energy to blog during the release...

But by now I feel recovered and want to start a little series about lessons we have learned while preparing the release and give some hints how to improve the performance of JavaFX Mobile applications.


WARNING: The tips I am giving here are true for the current version of JavaFX Mobile, which is part of the JavaFX 1.1 SDK. In future versions the behavior will change, the current bad performance of the mentioned artifacts will be optimized away or at least significantly improved. Everything I am writing about here is a snap-shot, nothing should be understood as final!


Item 1: Avoid unnecessary bindings

Bindings are very convenient, without any doubt one of the most valuable innovations in JavaFX Script. Unfortunately they come with a price. The generated boiler-plate code is usually not as small and fast as a manual implementation would be. Especially complex dependency-structures tend to impose a severe penalty on performance and footprint.

For this reason it is recommended to avoid bindings as much as possible. Often the same functionality can be implemented with triggers. One should not use bindings to avoid the hassle of dealing with the initialization order. And it certainly makes no sense to bind to a constant value.

Lazy bindings are most of the time (but not always!) faster if a bound variable is updated more often then read, but they are still not as fast as manual implementations.

Example

A common use-case is a number of nodes which positions and sizes depend on the stage-size. A typical implementation uses bindings to achieve that.

Here we will look at a simple example, which resembles such a situation. The scene consists of three rectangles which are laid out diagonally from the top-left to the bottom-right. The size of the rectangle is a quarter of the screen-size. Code Sample 1 shows an implementation with bindings.

 1 def rectangleWidth: Number = bind stage.width * 0.25;
 2 def rectangleHeight: Number = bind stage.height * 0.25;
 3 
 4 def stage: Stage = Stage {
 5     scene: Scene {
 6         content: for (i in [0..2])
 7             Rectangle {
 8                 x: bind stage.width * (0.125 + 0.25*i)
 9                 y: bind stage.height * (0.125 + 0.25*i)
10                 width: bind rectangleWidth
11                 height: bind rectangleHeight
12             }
13     }
14 }

Code Sample 1: Layout calculated with bindings

The first question one should think about is wether the bindings are really necessary. On a real device the screen-size changes only when the screen orientation is switched (provided that the device supports this functionality). If our application does not support screen rotation, the layout can be defined constant.

One possible solution to reduce the number of bindings is shown in Code Sample 2. Two variables width and height are introduced and bound to stage.width and stage.height respectively. Their only purpose is to provide triggers for stage.width and stage.height, since we do not want to override the original triggers. Position and size of the rectangles are calculated manually in the triggers.

 1 def r = for (i in [0..2]) Rectangle {}
 2 
 3 def stage = Stage {
 4     scene: Scene {content: r}
 5 }
 6 
 7 def height = bind stage.height on replace {
 8     def rectangleHeight = height * 0.25;
 9     for (i in [0..2]) {
10         r[i].height = rectangleHeight;
11         r[i].y = height * (0.125 + 0.25*i)
12     }
13 }
14 
15 def width = bind stage.width on replace {
16     def rectangleWidth = width * 0.25;
17     for (i in [0..2]) {
18         r[i].width = rectangleWidth;
19         r[i].x = width * (0.125 + 0.25*i)
20     }
21 }

Code Sample 2: Layout calculated in trigger

Without any doubt, the code in Code Sample 1 is more elegant. But measuring the performance of both snippets in the emulator, it turned out the code in Code Sample 2 is almost twice as fast.

Comments:

Item 1 is completely true. We are so used to binding that we put bind before every line.

Posted by Vaibhav Choudhary on February 23, 2009 at 05:40 AM CET #

Yeah, but I think ultimately, the best desirable solution is to have the compiler be smart enough to optimize out the binding cases so that the developer wouldn't have to worry about extraneous, unnecessary bindings. Kind of like what HotSpot does now with loops and the inlining stuff. Binding is such a core concept to JavaFX that I would really hate to be self conscious about using it.

Posted by Mike on February 23, 2009 at 05:36 PM CET #

"And it certainly makes no sense to bind to a constant value."

Aha! I was puzzled to see sometime
someProperty: bind "SomeString"
I am happy to see confirmation that it is useless!

I suppose in the future the compiler will not generate binding for these expressions (or a warning, which could be better, as a way to better code writing...).

Interesting trick, for sure. Thanks.

Posted by Philippe Lhoste on February 23, 2009 at 06:30 PM CET #

Hello, how do you post code parts in blogs messages?

Posted by Michael on March 04, 2009 at 08:01 PM CET #

I am using NetBeans to generate the html-code. The functionality is called "Print to HTML" there. You just have to define the style in your CSS-file to get the syntax highlighting.

Posted by Michael Heinrichs on March 09, 2009 at 04:58 PM CET #

Thx for the tips...were really helpful in my project of developing an application to take part in Nokia's Calling All Innovators, 2009 contest. Will be back with more when I make some more progress.

Posted by rob on April 03, 2009 at 09:52 AM CEST #

Post a Comment:
  • HTML Syntax: NOT allowed