JavaFX – Performance Optimization


Bookmark and Share

There was a question related to Best Practices for speed optimization in Oracle-Mix forum. There are many small tips & tricks, just thought of listing out what ever came to my mind..

Use Layout: For positioning node always use Layout. There are plenty of layout available such as HBox, VBox, Tile, Flow and Stack. If we need any custom layout you can use Container or Panel. Position node using layoutX and layoutY attributes. Use translateX and translateY for Animation.

Consolidate Theme Attributes : We can reuse many theme related objects such as Font, Color, Paint, Image. Eg: If we use same Font for many Label/Text, we can use the same Font instance instead of creating one each for each instance of Node. This consolidation also allow us to customize the UI. You may refer to Theme used in Calendar sample. Also share Image instances such as default-image, place-holder image etc across multiple objects.

Bind with Caution: I have stressed on this in one of my previous post. Repeating the same again. Use this mostly for wiring model to view. Minimize use for other purpose such as layout of Nodes. Also better to avoid chaining of binds, its very problematic and difficult to debug.

JavaFX for View: There is a tendency to write entire application using pure JavaFX. This may be fine for small widget like application or samples. But when you write real business application we need to push out the business logic, IO operations and non-ui related code to Java layer. Use JavaFX Async APIs + Callback methods so as to execute these code outside Event-Dispatch-Thread. HttpRequest API demonstrates use of this approach.

Reduce use of Effects: In many cases we may need to have static effects in UI, such as nice gradient for background, font effects etc. If these effects are static, its always better to use Image instead of effect API.

Stroke Vs Fill: Instead of using stroke attribute for shape, we may use nested shapes with fill attribute. Example: For creating a stroke for Rectangle, we can create two instances of Rectangle overlapping, with the inner Rectangle smaller than outer Rectangle. This will have better performance compared to use of stroke attribute.

Avoid Class-Path in Manifest: When we add various jars as library to Netbeans, these jars are directly referenced in Class-Path of Manifest file of the application jar. When deployed, this will force to download all jars before start of application. Concept of lazy download will not work. Also there will be an attempt to make an unnecessary network connection, even though resources such as plugin.jar, javaws.jar etc are not hosted. This will increase initial applet/javaws startup time.

Use Image.width & Image.height: If we need to show a thumbnail of large image, its better to specify its width and height Image object itself rather than resizing the ImageView using fitWidth and fitHeight attribute. This will reduce the memory used to hold the image.

Provide Startup Feedback: Many a times people get bored due to lack of proper feedback during startup. This creates a notion of increased startup time. Except for small use-cases such as advertisements, RIA’s do have some startup time. It will be nice to provide a Custom Splash Screen and even better a Progress Listener UI to give useful feedback.

Tips for Mobile: : Joshua Marinacci has listed some useful tips for mobile.

I’m sure there are more… ‘ll keep updating this list… 🙂

Advertisements

Java Download Service Listener


Bookmark and Share

One of the previous post [Applet Startup Time] provided a way to measure start-up time of JavaFX Applets. Many responded with requested information (Thanks a lot!). One of the main concern raised was high start-up time for “Without JavaFX Runtime”. This is high because it includes time taken to download and install JavaFX Runtime.

Unfortunately there was no way to notify the user about exact progress of this. Hence user will not be able to differentiate between download and install of “JavaFX Runtime” and “JavaFX Application”.

Recent JavaFX Update 1.2.3 reduced the download size and start-up time. You can notice this change by trying out the start-up time measurement applet again.. But still it doesn’t provide a way to exactly notify the start-up progress. We can only specify a custom splash-screen as specified here.

And then we have Java Update 1.6.0_18 Not sure how many of you noticed this feature – Download Service Listener It allows you to provide a Custom Progress UI using AWT/Swing/Java2D APIs. It has callback methods which will provide information related to download and validation of resources. Please refer to Download Service Listener Example for more information. Refer to ProgressListener.java and ProgressView.java for implementation used in this sample.


To launch click on above image or

Now we can implement custom progress listener with actual values. We can use the same approach for JavaFX applications as well. There is minor issue in using this feature with JavaFX Applet deployed using dtfx.js. This script is not updated to utilize this feature. So for now we need to explicitly hide the default splash screen by invoking JavaScript method hideOverlay as shown in ProgressListenerFX.html

Reference:

Hmm.. thatz a long post with lots of information.. But I think its very useful.. As usual, please try it out and let me know feedback..

JavaFX – FPS Meter


One of my previous post mentioned about way to specify Z-Order for JavaFX Nodes. Just thought of putting this approach to use in a carousel. There are lots of interesting samples available at shinedraw.com – Flash vs Silverlight Repository. Below is JavaFX port of FPS-Meter..





To launch click on above image or Click to add more images.

Note: The icons used in this sample are from MouseRunner.com licensed under the Attribution-ShareAlike 3.0 Unported.

I did some monitoring with JConsole. It was giving consistent 60 fps for 50 nodes with average 13% CPU usage. JConsole details available here. I’ll leave it to experts to come up with proper conclusion…

Launch JavaFX FPS Meter. Start JConsole and select the process
com.sun.javafx.runtime.Main javafxfpsmeter.Main
from “Local Process” list.

System Information:

  • JavaFX: 1.2.1 (public)
  • JavaSE: 1.6.0_16
  • OS: Windows Vista
  • Processor: Intel(R) Core(TM)2 Duo CPU T7300 @ 2.00GHz
  • Memory (RAM): 1.00 GB
  • Display: NVIDIA Quadro NVS

There is significant performance improvement done in different components of JavaFX for next release.. Stay tuned.. I will share the statistics with exactly same test and same system so as to compare the improvement..

Please try it out and share your information and thoughts..

var dzone_style = ‘2’;

To Pack or not to Pack?


I’m back from vacation.. Hmm.. well it was not this long though.. (my last post was more than a month back).. I traveled to few places, exploring new things.. You may view the some of the photos here!

Well was busy with many other things as well..
Oracle OpenWorld, Mobile Application Conference..

Anyway back to the topic.. Is it always good to compress the jar while deploying the Java/JavaFX application? What will be its impact on startup time? Or may be I was doing too much pack and unpack of luggage during vacation and hence the thought is still lingering in my mind?!

I think the answer depends on the application and target users. Pack helps to compress the jar file size (reduce download time). But it may increase the start-up time due to additional step – unpack. So if the application is too small, it may be better not to use compressed jar. Also if the target audience has very good bandwidth, then user may not see the benefit of reduced download time.

Applet – Pack Applet – No-Pack

Note: Above example is not the best to demonstrate any significant difference in warm start-up time

Also set update check to background in jnlp files as shown below.. Please refer to tech tip on start-up time for more information.


<update check="background"/>

JavaFX packager was generating jnlp files with missing / for close tag for applet-desc – param tag. Due to this any subsequent tags were getting ignored. So we need to ensure that all tags are properly closed. This issue with javafxpackager is resolved (not be available in 1.2)


<applet-desc ... >
    
<param name="MainJavaFXScript" value="..." />
</applet-desc>

Best way to validate the jnlp is to launch the application and view the jnlp in Java Cache Viewer. Ensure that all entries are reflected properly. Update check must be set to “background” and not “timeout”.

Well.. I never thought that one character (or lack of it) can contribute so much towards start-up time! Keep exploring!!

JavaFX – Applet Startup Time


Bookmark and Share

We keep getting various numbers related to JavaFX applet startup time. Yes this is very important and we need a consistent way to measure this and compare. Here is an attempt..

Update:

When the page is loaded, the system time is noted using JavaScript. Time is again noted once Applet is loaded. Difference between time obtained in Applet and JavaScript is computed to be startup time. I think this will be fair and consistent way to measure startup time. This requires JavaSE 6 Update 10 and above. It will be good to try out a few times and get the average number..

User Without JavaFX
Runtime
Load
Applet
Re-load
Applet
Rakesh Menon 45 3.00 0.70
Pär Dahlberg 7.27 0.66
Julien Buret 1.71 0.32
cozmint 7.83 1.55
Philippe Lhoste 3.42 0.98
Ernie Kent 4.73 0.66
Carl Dea – FF 5.74 0.63
Carl Dea – IE 3.34 0.74
Simon Brocklehurst 3.12 0.79
Tom Eugelink 2.68 0.64
Guido 2.56 0.62
GC – WinXP-64bit FF-64bit Error
Carl Antaki 4.06 0.67
Nick Apperley 3.27 0.83
Andy Xie 47 8.32 1.05
Wojciech Halicki-Piszko 4.45 0.8
Endre Stølsvik 72 3.80
Chui Tey – Chrome 2.0.172.43 6.95 2.86
Chui Tey – MSIE 8.0.6001.18702IS 3.22 0.70
Chui Tey – FF 3.0.10 4.13 0.70
JosK (Intel Core 2CPU 4300@1.8GHZ (1,93GB)
512RAM) – Chrome 2.0.172.43
4.26 4.08
JosK (Intel Core 2CPU 4300@1.8GHZ (1,93GB)
512RAM) – Chrome 3.0.195.21
3.98 1.05
JosK (Intel Core 2CPU 4300@1.8GHZ (1,93GB)
512RAM) – IE 8.0.6001.18702
8.33 1.06
Jonathan (Quad Core Q9300 @ 2.5GHZ, 4GB ram JRE 1.6u15) 15.50 0.52
Thierry (2 year olds windows dual core basic PC) 17.50 3.10
Robrecht (Windows xp SP2 Intel Core 2 cpu T5600 @ 1,83GHz, 2GB Ram jre: 1.6.0_15) 4.83 2.80 0.62
Venkateswara Rao Desu (Fedora 9 JDK 1.6_10) Applet not initialized
André Costa 1.91 0.42
Joeri Sykora (jdk 1.6.0_16 in Firefox 3.5.3) 1.02 0.65
Thustle (1.6.0_16 on Chrome v3 on Vista 32bit Intel Core2 Quad Q6600 2.4GHz 4GB) 9.30 0.74
Vance (Intel Core 2 Duo P8700 2.53GHz/1066Mhz RAM:4GB, DDR3, 1067 MHz, Ubuntu 9.10, FireFox 3.5.5, JRE: 1.6.0_15, Connection: comcast high-speed cable) 7.6 2.3 0.3
Venkateswara Rao Desu (Fedora 11 Firefox 3.5.5 Sun Java Plugin) 17.00 0.70
Venkateswara Rao Desu (Windows XP Java 1.6.0_18) 9.3 0.38
Jor (WinXP, FF 3.5.7, Java 1.6.0_17) 36 0.21
Galien (IE8 64 bit, 1.6_18 Vista 64bit, intel i720, sata 10k rpm) 11.92 0.28 1.17
Galien (FireFox 3.6 32 bit, 1.6_18 Vista 64bit, intel i720, sata 10k rpm) 12.10 0.15 0.15

Legend:

  • Without JavaFX Runtime – After clearing Java Web Start cache – [ javaws -uninstall ] May have to wait for sometime as clearing process may be running in background. This is the time taken to download JavaFX runtime and load the applet.
  • Load Applet – Launch browser and load applet (JavaFX runtime already installed)
  • Re-Load Applet – Re-load the page after loading applet
  • Duration – specified in seconds

Please launch the applet and let me know the start-up time with system configuration and connection speed.. Thanks in advance..

JavaFX – Lazy Loading


It will be nice if we could break down the application into smaller modules and load the modules as and when its required. This will significantly reduce the start-up time. Here is an attempt to perform lazy loading of javafx modules.

A list of samples is shown. User can select the sample to be loaded from this list. The samples are dynamically loaded from JavaFX Samples. The sample is loaded using URLClassLoader. Then its instantiated and content of stage (JFrame) is obtained and added to main application.

Click on above image to load the Applet

This is an experimental implementation, just to try out the approach. There are issues with focus (cursor not shown on TextBox, but can still type), multiple Stage (JFrame) and may be some memory leak. The content is initially shown on another frame. Then its removed from original frame and added it to main frame. This causes some flickering. The implementation can be enhanced a bit so as to use some internal APIs and make things a bit more elegant. In any case I think the next version of JavaFX will have built in support for this. Which will be much more stable and flexible.

Disclaimer: Its an experimental implementation. Not concrete yet. Yes it can be enhanced. I just thought of putting it out so others can try to enhance it..

Source:

JavaFX – Bind with Caution!


JavaFX “bind” and “on replace” are really nice and useful features. But recently I came across many misuse of this feature which results in performance issues. Here we will look into couple of common usage which leads to performance issues..

An example application is shown below…

For Applet mode, click on above image

For standalone mode

Example: In below code, the user wants to perform “update” operation when ever there is any change in x, y, w and height. The initial values of these variables are set to 0. Later as and when the application is shown on screen, actual values of these are updated.


var x = on replace update()}
var y = on replace update()}
var width = on replace update()}
var height = on replace update()}

function update() {
    /**
     * Performs complex update process!
     */
}

But during this process, the “update” method is invoked 8 times! 4 times when the variable is initialized to 0 and another 4 times when the actual value is set. Instead if we perform a simple check to ensure that all variables are set before update, we could have easily avoided performing the complex operation so many times and improve performance.


function update() {
    if((x > 0and (y > 0and (width > 0and (height > 0)) {
        /**
         * Performs complex update process!
         */
    }
}

Another common usage is binding to value of Slider or ScrollBar. Objective is to perform some operation as and when the value is updated by user.


var slider = Slider {
    min: 0
    max: 100
    value: 50
}

var sliderValue = bind slider.value on replace {
    /**
     * Perform Complex Operation!!!!
     */
}

But this will end up performing the operation many many times before the actual value required by user is set. Also the slider won’t be responsive, since we are constantly repeating the task. So instead of performing operation for each and every value with in the interval, we may just wait for few milli-seconds before performing the actual operation.


var slider = Slider {
    min: 0
    max: 100
    value: 50
}

var timeline = Timeline {
    keyFrames: KeyFrame {
        time: 50ms
        action: function() {
            /**
             * Perform Complex Operation!!!!
             */
        }
    }
}

var sliderValue = bind slider.value on replace {
    timeline.playFromStart();
}

In above code a Timeline is started when ever the user changes the slider value. The actual operation is performed only after few (50ms in above code) milli-seconds. This will ensure that we won’t perform complex operation until user settles for a value.

Also bind is used for layout of nodes along with boundsInLocal, boundsInParent etc. Instead try to use various layouts such as Flow, HBox, Panel, Stack, Tile, VBox and LayoutInfo.

Also refer to Girish’s blog which talks about another common performance issue related to dynamic update of nodes.

These are not the only issues or only solutions, the objective is to just caution the usage, so that you can optimize the code as per your requirement. Try it out and let me know feedback

Source: