Skip to main content

JavaFX Balls v2.0: Better benchmarking, Mobile support

Posted by opinali on March 4, 2009 at 7:49 AM PST

In a previous blog entry I described JavaFX Balls, the bubblemark benchmark for JavaFX 1.0. Now I took some time to improve the benchmark and also make a Mobile version!

Going Adaptive

In a forum discussion involving JavaFX Balls and the bubblemark, Dmitri Trembovetski complained that "Gunning for maximum fps in this benchmark is meaningless". Other posters think the current benchmark is valuable, it depends on what you want to measure; but I agree with Dmitri that scores nearing 1000fps are not representative of real-world apps.

So, I enhanced JavaFX Balls with a new option of Adaptive ball count. Click that option, and the program resets at 128 balls but changes that number dynamically, at each 3s intervals, until reaching a stable performance that's close to 200fps (up to 5% higher or lower). The display that's layered on top of the animations is now a string like "29? Image Balls, 198fps". The "?" means that the ball count is unstable (changed in the last FPS update); when you select Adaptive, you must wait until this question mark disappears.

UPDATED: I removed this old version of JavaFX Balls, mostly to make sure nobody will use it anymore as a benchmark because it suffers from JavaFX 1.0's performance. Please check the latest version, for JavaFX 1.3.

Going Mobile

One of JavaFX's most interesting qualities is desktop/mobile portability. It's not perfect, as JavaFX is not a self-contained platform (need SE/ME APIs for such mundane tasks as file I/O); and because, frankly, it's not yet complete - for one thing, JavaFX's native (SceneGraph-based) component set is still missing in v1.1, so your choices are either writing your own components, using platform-specific code or waiting until 1.5. But having said that, even at this stage JavaFX offers a very impressive set of cross-platform capabilities.

Enough talk, here is the Mobile version of JavaFX Balls (also showing the result of the Adaptive mode). Get the full source code for NetBeans, with both versions (check the README.TXT).

JavaFX Mobile

Follows an account of all changes I had to do, to produce this Mobile version:

  • Refactored all platform-specific code (the "Control UI") in a single place: MainDesktop.fx (~60 LOC) and MainMobile.fx (~50 LOC). The desktop version is still the same toolbar using javafx.ext.swing. The mobile version has no visible Control UI, it's completely keypad-driven:
    • LEFT reduces ball count, RIGHT increases it. Notice that I don't inc/dec the count - I cycle to the previous/next element of a sequence of standard ball counts just like the radio buttons in the desktop version;
    • UP toggles Image/Vector rendering;
    • DOWN Starts/Stops animation;
    • STAR toggles the Adaptive mode.
  • The enhanced FPS display includes information that would be missing in the mobile UI, like ball count; but this happens to be a nice enhancement even in the desktop UI. (I also fixed the code so every time the animation is reconfigured because the user changed ball count or other option, the FPS counter is properly restarted with a new start time.)
  • The original code used a javax.swing.Timer for the FPS updates. This API doesn't exist in CLDC/MIDP, but it's unnecessary (and probably yet another artifact from the original code being ported from a Swing version). I just used a secondary Timeline.
  • I'd changed the original code to use System.nanoTime() (stupid!), now I had to go back to System.currentTimeMillis() because it's available in CLDC. This sucks because currentTimeMillis()'s precision is just ~15ms. JavaFX really needs its own hi-res clock API. For JavaFX Balls it's not a big issue because I use that only to measure FPS each 3s, so max error is ~0,5%.
    • Note: The program (since its original version) only reads the clock because we can't trust the timer to fire in exact deadlines - it's not a hard-RT platform, so jitter can be high. The time interval calculation could be removed otherwise. Another minor detail that must be considered in good benchmarking code.
  • The code used a java.awt.Insets object for the walls boundary data; another leftover from porting from the port from Swing. I fixed it to use javafx.geometry.Rectangle2D.
  • The program used Math.random(), a convenience method that's not available in CLDC. Fixed it with java.util.Random.
  • I changed the standard set of ball counts from [1, 10, 16, 32, 128] to [1, 4, 10, 16, 32], due to the lower resolution (~1/2 of the desktop's). I kept the default setting of 16 balls; this will result in a higher (quadratically?) number of collisions, but that has insignificant cost and people will want to directly compare the desktop and mobile scores.

I didn't attempt to make the mobile program adapt to the device's screen resolution; it's hardwired for 240x320 (QVGA), a popular resolution for MSA-Subset (or better) devices, and arguably a minimum resolution for any RIA-capable device. JavaFX Mobile will probably run on JTWI devices with a decent MMAPI and lower resolutions like 176x220, but I doubt JavaFX will be very cool or efficient on older devices that also have much worse CPUs, color depth, etc.

And JavaFX Mobile is not really released; we (outside Sun) can only test in the beta emulator. After JavaFX Mobile is released and I can test it on real devices, I'll revisit the code as necessary. I'd appreciate if the authors of other bubblemark versions would port them to mobile runtimes - Flash Lite, Silverlight for Mobile, MIDP with the LCDUI or other JavaME APIs, etc.

How good is JavaFX Mobile's performance? I've got a 82 Balls score for 25fps (which is the locked FPS target for Adaptive mode on Mobile). This consumed 52% CPU (laptop with a dual core T7250 CPU, so that's roughly a full core). I picked 25fps as a standard because the emulator in the beta Mobile release used that rate as the default PULSE_DURATION, but also because 25fps makes sense for devices (it's good enough, and each extra FPS costs you in battery). But the performance is obviously just a curiosity for an emulated, beta runtime.

Comments

Removing the dependency

I whipped up this little method for setting the "com.sun.scenario.animation.pulse" property, this removes the dependency on the Scenario.jar file, makes the netbeans project a little nicer to work with.
public class Bench {

//com.sun.scenario.Settings.set("com.sun.scenario.animation.pulse", "1000");
public static boolean setup(){
try{
Class clazz = Class.forName("com.sun.scenario.Settings");

Method method = clazz.getMethod("set", String.class, String.class);
method.invoke(null, "com.sun.scenario.animation.pulse","1000");

return true;
}catch(Exception e){
throw new RuntimeException(e);
}
}
}


and then call this in MainDesktop.fx, something like:

var result = Bench.setup();


Thanks for the cool demo!
- Lucas Jordan

Please forgive the formatting... java.net's comment system has always given me fits :)

That's a good idea, thanks!

I have also noticed that with each NetBeans and/or JavaFX SDK update, the path for the scenario API changes and even my own project configs have to be fixed. I will use something similar in future updates of my benchmarks (just waiting for JavaFX 1.3...), I guess will just eat the exception instead of rethrowing, to be better-behaved with future JavaFX runtime releases as these internal APIs are not guaranteed to remain backwards-compatible.