Performance: JavaFX Balls

As soon as I've got JavaFX 1.3 and NetBeans 6.9-beta, first thing I did was obviously running benchmarks, and the new update delivers on its promise. Let's first check JavaFX Balls (port of Bubblemark). I've last reported results for 1.2 here; but scores for 1.2 are updated again to account for changes in my test system, remarkably the JDK (now 6u21-ea-b03).

TestJavaFX 1.2           
JavaFX 1.2           
JavaFX 1.3           
JavaFX 1.3           
JavaFX 1.3           
JavaFX 1.3           
1 Ball999 fps1000 fps1000 fps1000 fps  
16 Balls998 fps998 fps1000 fps1000 fps  
32 Balls986 fps998 fps998 fps998 fps  
128 Balls490 fps636 fps608 fps666 fps  
512 Balls90 fps108 fps124 fps151 fps  
@ 60 fps642 Balls699 Balls815 Balls878 Balls817 Balls1.173 Balls
@ 200 fps285 Balls358 Balls366 Balls428 Balls  
Effect, 1 Ball666 fps666 fps666 fps972 fps  
Effect, 16 Balls150 fps165 fps162 fps220 fps  
Effect, @ 60 fps44 Balls47 Balls45 Balls66 Balls377 Balls642 Balls
Effect, @ 200 fps12 Balls13 Balls12 Balls14 Balls  
2D, @ 60 fps70 Balls70 Balls68 Balls71 Balls96 Balls105 Balls
2D, @ 200 fps18 Balls20 Balls20 Balls20 Balls  
2D+Eff, @ 60 fps27 Balls28 Balls25 Balls26 Balls75 Balls82 Balls
2D+Eff, @ 200 fps7 Balls7 Balls7 Balls7 Balls  

JavaFX 1.3 shows once again good improvements in the scene graph's scalability - its advantage over 1.2 is bigger for higher node counts, topping at a 37% more fps for 512 Balls, or 28% more balls for 200 fps. JavaFX Balls is a worst-case animation in some aspects, all its nodes move every frame; in many real-world animations, some elements are either static (background) or semi-static (objects that only move or change when reacting to some event), so these will likely scale up to thousands of nodes as JavaFX uses standard tricks like dirty regions and bitmap caching to avoid redundant work.

The performance impacts of Vector rendering ("2D" tests) and Effects are unchanged: both options cost a lot. The Effects framework is the worst offender - a simple BoxBlur effect will bring your performance from 815 to 45 Balls (20X times worse) @ 60 fps. But..., this just for the standard graphics toolkit (identified as "Swing", because it's build on top of some core classes from the legacy AWT/Java2D/Swing stack).

Now let's activate the next-generation Prism toolkit (with -Xtoolkit prism; currently in Early Access). For the bitmap and vector tests, Prism is just as good as the old toolkit. But enabling Effects changes everything; Prism is almost 10X faster than the Swing toolkit, scoring an incredible 377 Balls @60 fps. Like long expected, Prism finally renders effects with full hardware acceleration and without the extra buffer copies that spoil effects on the Swing toolkit.

How good is Prism's score? I didn't focus on benchmarking against other RIA runtimes here, but these results are much better than the top scores I measured last June for PulpCore and LWJGL/Slick. The latter is a dedicated, lightweight 2D game engine and it's also OpenGL-accelerated, which makes Prism's advantage impressive. The Prism Bubblemark program is not available anymore (server down as I write this), but the latest PulpCore scores only 30 fps for 512 Balls. (PulpCore can do 65 fps with a new "Pixel snapping" optimization that rounds all coordinates to integer values - that looks interesting, I will add it to JavaFX Balls later.)

I've also repeated these tests with HotSpot Server. This VM is not viable for client deployment, but we can notice areas of possible improvement - anything that runs substantially faster with the Server compiler is (a) written in Java, and (b) has optimization potential. And we can really see HotSpot Server beating the pants off Client, in the simpler tests that only measure the scene graph's performance. Combining HotSpot Server with the Prism toolkit, I've broken the 1.000 Balls barrier for the first time in the @60 fps test.

Problem: When I add many balls in the JavaFX Balls animation in a single step, e.g. from 128 to 512 balls, the animation "freezes" for a noticeable time - close to a second. This happens because JavaFX relies on preprocessing (pre-allocating/computing objects that are reused at each frame for translations and other pipeline tasks). Prism's delay to add many nodes is not worse than Swing's, but not better either. My test case is perhaps extreme - most real-world animations should not add hundreds of nodes to the scene in a single keyframe. Anyway this shows one possible bottleneck that may deserve optimization in future releases.

Performance: Strange Attractor

My next test is the Strange Attractor benchmark. I didn't expect any improvement in this program, because it makes minimal use of JavaFX's scene graph - all animation is performed by manual writing of color values to a large array of pixels that is finally blitted to the screen.

TestJavaFX 1.2           
JavaFX 1.2           
JavaFX 1.3           
JavaFX 1.3           
MainListDouble74 fps96 fps80 fps94 fps
MainSeqDouble62 fps77 fps65 fps78 fps
MainFloatRaw144 fps166 fps162 fps250 fps
MainListDouble3D62 fps78 fps50 fps64 fps

The performance delta was modest as expected - except for the large improvement in MainFloatRaw with HotSpot Server, and the regression in all scores for the MainListDouble3D test. The latter test has extra code inside the inner rendering loop (for smarter calculation of pixel colors), so the smaller performance may just be some unlucky effect of different javafxc code generation over JIT optimizations.

Why no scores for Prism? The Strange Attractor program had to be ported, because it reaches into Image.platformImage, which I empirically found to be a java.awt.image.BufferedImage (containing a DataBufferInt) in previous releases - and still in JavaFX 1.3 with the Swing toolkit. But Prism's runtime type is com.sun.prism.Image; inside this object there is a java.nio.HeapByteBuffer object that contains the pixels. And the pixel data was only 8bpp, because the Image was created from an 8bpp blank.png file. Well, I changed the code that reaches to the pixels and recreated this PNG at 32bpp. But the program still doesn't work - the image has wrong colors, and I can only see the first frame because my trick to force refresh (calling ImageView.impl_transformsChanged()) has no effect on Prism. I've tried other methods, including some with promising names like impl_syncPGNodeDirect()... but nothing makes Prism sync the window with the updated pixel buffer. I'll be happy to hear about your findings, otherwise we cannot efficiently program bitmapped animation for JavaFX anymore. Another problem is that performance sucks - I get only ~29fps with full usage of one CPU core, and that's without any refresh.

Performance: GUIMark

GUIMark is one benchmark that used to be a disaster for JavaFX, as I briefly reported before. The problem is tracked by bug RT-5100: Text layout in FX is much slower than a pure Swing app. The root cause of this umbrella bug is RT-5069: Text node computes complete text layout, even if clipped to a much smaller size. These bugs are still open - although they report some progresses; for one thing, part of the problem is blamed to the JavaSE's Bug 6868503: RuleBasedBreakIterator is inefficient, and that bug is closed as fixed in JDK 6u18. So I decided to test GUIMark again.

ProgramJavaFX 1.2           
JavaFX 1.2           
JavaFX 1.3           
JavaFX 1.3           
JavaFX 1.3           
JavaFX 1.3           
GUIMark1,81 fps2,22 fps2,81 fps4,44 fps78 fps120+ fps

Text layout performance is better in JavaFX 1.3, but the bug is still alive; the ~2X better scores are still awful. But, that's only true for the Swing toolkit. Prism doesn't suffer that problem, delivering wonderful GUIMark scores.

Notice that I've tweaked the benchmark to use a 0ms keyframe, and used JavaFX's internal FPS logger. It's the only way to allow maximum FPS count when the animation runs too fast, and at the same time, get precise performance numbers when it runs too slow. Also, I cannot measure the real score for Prism / HotSpot Server because Prism caps fps at 120 - but in my system this test consumes 20% CPU (0,8 core in a quad-core system), so I can project ~150 fps.

In the same test machine I get these scores: Java / Swing = 43 fps (Client) / 50 fps (Server); HTML (Firefox 3.7-a4, with DirectDraw & DirectText enabled) = 47 fps; Flash 10.1rc2 = 53 fps; Silverlight 4.0 = 55 fps. Thanks to Prism, the Order of the Universe will be restored, with Java's performance ruling once again.

The other GUIMark implementations are also capped, either by their own code or by their runtimes. I removed this limit only for Java/Swing, changing a timer's delay from 17ms (= max 60 fps) to 5ms (= max 200 fps); but as I expected there was no effect in the performance because the program cannot reach even 60 fps. The HTML, Flash and Silverlight programs can't reach 60 fps so they're not limited by capping. Additionally, they all saturate the CPU - HTML uses a full core (25%), Flash uses a bit more (30%). Silverlight uses two full cores (50% of my quad-core CPU!), very surprising because I didn't run the multithreaded version of the benchmark, and because the score is actually terrible considering that it consumes 2X more CPU power than other runtimes that deliver similar fps ratios.

GUIMark was designed to measure only a RIA runtime's animation & graphics pipeline - layout, drawing and composition engines; it doesn't run any significant amount of "application code", so it should not benefit from a more efficient language and JIT compiler... Except of course, that JavaFX eats a lot of dog food - its core runtime is partially Java bytecode. But it also contains significant native code (including "GPU-native" shading code), and remarkably in Prism I wouldn't expect the Java code to be critical; still, HotSpot Server consistently makes a big difference: roughly double GUIMark performance. Profiling the VM, I noticed that HotSpot Server optimizes java.nio's direct buffers much better, as well as some other APIs involved in bulk data manipulation like Arrays.fill(); these methods are all over Client's profile but totally absent in Server's (which means intrinsic compilation). Prism heavily relies on these methods for the interface with the accelerated pipeline (D3D in my tests on Windows). This seems to hint that even after Prism ships, JavaFX performance could gain yet another significant performance boost: the Client VM just needs to acquire a few critical optimizations that are currently Server-exclusive.

Static Footprint

JavaFX 1.3 promises many performance enhancements, including reduced startup time and memory usage, and this is critical because - remarkably now with 1.3's already very good core feature set - deployment is by far the most important factor for JavaFX's adoption.

ProgramJavaFX 1.2JavaFX 1.3
HelloWorld2 classes, 2.726 bytes2 classes, 2.579 bytes
JavaFX Balls19 classes, 95.19 bytes19 classes, 117.005 bytes
Strange Attractor62 classes, 563.769 bytes62 classes, 427.992 bytes
Interesting Photos53 classes, 238.902 bytes46 classes, 431.741 bytes
GUIMark9 classes, 93.841 bytes27 classes, 224.904 bytes

The tally of compiled classes, for these few programs, shows a regression in javafxc 1.3 - it may produce 25% less bytecode (Strange Attractor), but will most often produce more bytecode, up to 140% more (GUIMark).

Strange Attractor is the single app (except the trivial HelloWorld) that consists in a single .fx script file (more exactly, several .fx files, but they are all independent variations of the same program). The javafxc compiler can perform some important "closed-world optimizations": for example, a private or script-private property that is not involved in any binding expression in that script can be compiled without support for binding. On the other hand, when this overhead cannot be optimized out, generated code is typically bigger than in 1.2 - largely thanks to the awesome enhancements of compiled bind, that delivers higher-performance binding with a tradeoff in more sophisticated code generation. But even for the applications that have bigger static footprint like Interesting Photos, we are promised a net gain because the dynamic footprint is greatly reduced (no expression trees for interpretation of bound expressions); so you loose some Kb in code size, but you win more than you've lost in reduced heap usage. (This is the theory - but check the next section!)

JavaFX Optimization Rule: Fine-grained decomposition into many small .fx files, with generous public members, will balloon the code footprint of your JavaFX app. Even if this is more than compensated by reduced dynamic footprint, you want both costs down if possible! Existing bytecode optimizers/obfuscators for Java (e.g. ProGuard) may help a bit, but won't be optimal as javafxc's code generation is very complex, and performing the closed-world optimizations I mention above is not just a matter of stripping unused class members. Suggestion: add a javafxc option to request these optimizations for all public properties in a project, assuming that no external, separately-compiled code will have "incoming binding" on our code - that's a safe assumption for most JavaFX apps (but not for libraries).

Finally, the worst-case of GUIMark is related to binding: this programs makes some extensive use of binding - 53 bind expressions, in a program that has 430 lines including spaces and comments. The "compiled bind" system seems to be as heavy on the call sites, as it is on the definition of bound variables. The program is also written in a very "scriptish" style, 80% of it is variables and functions in the global scope, it's possible that a more OO style with higher encapsulation would help the binding optimizations. Notice that compiled bind is not really complete; no less than 9 compiled bind optimizations have slipped into JavaFX "Presidio" (1.4). This includes at least one item that would apparently remove the code bloat at call sites: JFXC-4199: Use a delegate class instead of creating a new class for objlit.

ProgramJavaFX 1.2JavaFX 1.3           
JavaFX 1.3           
HelloWorld1.660 classes1.717 classes984 classes
JavaFX Balls1.847 classes1.885 classes1.111 classes
Strange Attractor1.894 classes1.996 classes1.201 classes
Interesting Photos2.095 classes2.032 classes1.193 classes
GUIMark2.033 classes2.207 classes1.360 classes
AWT HelloWorld1.050 classes
Swing HelloWorld1.206 classes
Swing GUIMark1.511 classes

In the table above, I run each program with -verbose:gc and check the number of loaded classes up to the startup screen. JavaFX 1.3 loads a few more classes in 3 of the 4 tests; some tiny average increase is expected considering its much increased feature set, but it's nothing to worry about.

On the other hand, Prism turns an impressive win: a minimal HelloWorld program loads less than a thousand classes, saving 60% off the Swing toolkit. We shave off 733 classes for HelloWorld, 839 classes for Interesting Photos. The latter is still a simple program, not even completely loaded - I stop counting when the initial screen appears, before any action or user event - but this is the right way to measure startup overheads. For a bigger real-world app the ~800 classes saved by Prism may be a small fraction of all loaded classes; but this is irrelevant for loading-time experience if the app is able to display its welcome screen quickly and then load the rest of classes and resources on demand or in background.

Just ask Flash developers: it's hard to walk into a real Flash app (excluding tiny widgets like menus, animated ad banners, or video-player shells) that doesn't need incremental loading techniques - including the infamous loading progress animations. Still, Flash gets a rep of "instant-load" experience, just because it bootstraps fast - the core runtime and the application's startup code are able to load quickly. When JavaFX can do the same, we are in competitive territory.

Looking at the classloading stats for standard JavaSE applets, they are almost as lightweight as JavaFX+Prism - an AWT-based HelloWorld applet loads 66 extra classes (6% more), a Swing version loads 222 extra classes (22% more). JavaFX sans Prism has the worst classloading story, because it combines two graphics/GUI toolkits, as the JavaFX stack is layered on many core classes from AWT, Java2D and even Swing... JavaFX was initially a big regression in bootstrapping costs. Prism not only fixes this regression, it's even more lightweight than the legacy APIs, which is impressive. Sun has really faced the challenge to dump a huge piece of Java legacy and rewrite it from the ground up, introducing a full-new toolkit that has zero dependency on the old one. There are more advantages in this approach, like starting from a clean slate (no need to support bug-per-bug backwards compatibility with 15 years of legacy), embracing modern architecture (GPU acceleration), and much better portability (Prism is reportedly very portable across OSes and even JavaFX profiles; the JavaFX TV is built on CDC + Prism, and inspection of the SDK's jar files apparently shows that Prism shares more components with the Mobile runtime too).

Sun has really pulled a Swing Killer of their own. Too bad that IBM's SWT, for all the secession it caused in the Desktop Java ecosystem, only focused on conventional, GUIs, without much thought for graphics/media-rich apps or direct tapping of GPU capacity... perhaps it was too early for that in ~2001. The fact is that JavaFX+Prism renders obsolete not only all of AWT/Java2D/Swing (and JavaME's LCDUI and more), but also SWT/JFace. The Eclipse Foundation seems to only believe in pure-HTML RIA, they are only evolving their RCP technologies towards the web (RAP & RWT), so JavaFX is the major option forward for Java rich GUIs apps that can't fit in the feature and performance envelopes of HTML5 + JavaScript.

Dynamic footprint

In the last test, I look at each program's memory usage, using -XX:+PrintHeapAtGC and executing jmap -histo:live <pid> on the JVM after it was fully initialized (this triggers a full-GC on the target VM, so I can see precise live-heap stats).

ProgramJavaFX 1.2JavaFX 1.3JavaFX 1.3           
HelloWorldHeap: 628K         
            Perm: 2.716K
Heap: 671K         
            Perm: 3.318K
Heap: 421K         
            Perm: 3.199K
JavaFX BallsHeap: 1.085K         
            Perm: 3.685K
Heap: 801K         
            Perm: 4.161K
Heap: 635K         
            Perm: 3.779K
Strange AttractorHeap: 13.876K         
            Perm: 3.764K
Heap: 18.448K         
            Perm: 4.306K
Heap: 17.629K         
            Perm: 3.957K
Interesting PhotosHeap: 2.073K         
            Perm: 4.264K
Heap: 2.039K         
            Perm: 5.308K
Heap: 739K         
            Perm: 4.501K

JavaFX 1.3 uses significantly less heap memory than 1.2 for JavaFX Balls; a bit less for Interesting photos, a bit more for HelloWorld, and a lot more for Strange Attractor. The latter creates a big linked list of tiny Particle objects, and I wouldn't expect these objects (simple {x, y, z, next} class) to have a different footprint, so I decompiled the classes emitted by javafxc and checked the instance fields emitted for the Particle class. For JavaFX 1.2:

int VFLGS$0;
public double $strangeattractor$MainListDouble$Particle$X;
public double $strangeattractor$MainListDouble$Particle$Y;
public double $strangeattractor$MainListDouble$Particle$Z;
public Particle $strangeattractor$MainListDouble$Particle$Next;

Now let's check JavaFX 1.3:

public short VFLG$Particle$X;
public short VFLG$Particle$Y;
public short VFLG$Particle$Z;
public short VFLG$Particle$Next;
public double $Particle$X;
public double $Particle$Y;
public double $Particle$Z;
public Particle $Particle$Next;

The fields with VFLG$... names are bitmaps used by the binding system to keep control of which variables are dirty, needing reevaluation. JavaFX 1.2 used to need a single bitmap for the whole object (up to 32 mutable fields; objects with more fields could need additional bitmap fields). But now, it seems that JavaFX 1.3 uses extra control fields that are per each object field - possibly for lazy binding or other compiled-bind enhancements (see my past discussion of binding). This added four short values to my object = 8 bytes (possibly more with alignment), a ton of overhead for a class that will have 300K instances. The odd thing is that this class is script-private, and although its fields are mutable, they are never used in binding expressions - and javafxc 1.3 is supposed to be smart enough to remove these overheads for code that can benefit from closed-world (script-local) optimizations, remember? But it didn't work here; this may be a limitation or a bug. I wondered that the generated code could be better for the MainSeqDouble variant of the program (where Particle's fields are only modified at initialization), but it's exactly the same, even if I change the fields visibility from default (script-private) to public-init. (public-init fields can be modified after initialization; but only by code from the same script.)

In the bright side, JavaFX Balls's significant heap savings should be attributed to the larger number of scene graph nodes created by this program, even at startup with 16 balls. I repeated the test with the heaviest possible test: 512 balls, with 2D and Effect options. The heap usage was: JavaFX 1.2 = 13.703K; JavaFX 1.3 = 6.865K, JavaFX 1.3 (Prism) = 10.787K. Just like promised, JavaFX 1.3 saves a big amount of overhead for scene graph nodes. But it's remarkable that in this benchmark, Prism will consume more memory than the Swing toolkit and land in the middle of the scale from 1.2's 13Mb and 1.3's 6Mb. It's possible that Prism is more aggressive in optimizations that require more memory (for caches etc.), but this result may also just reflect its current beta-quality stage.

Finally, I looked at the "Perm" memory usage (PermGen, the region used by HotSpot to store code for loaded classes). JavaFX 1.3 uses more memory than 1.2 (from +12% to +24% in my tests); but Prism loads less code than the Swing toolkit, so it almost reverts to 1.2's PermGen sizes (+2% to +17%). All tested benchmarks have little code of their own, so virtually all code comes from libraries: the JavaFX runtime and its dependencies in the JavaSE core. Even if JavaFX 1.3 has higher PermGen usage, this is probably much less important because the runtime has a fixed size, its cost doesn't scale linearly with application size or complexity (once you load all APIs and widgets, the runtime won't grow anymore for bigger apps).

[It's hard to assess GUIMark's dynamic footprint, because the animation cannot be paused; also the allocation rations are intense so the next section will be sufficient.]

Garbage Footprint

Having less objects retained in the heap is not that good if a program allocates too many temporary objects, causing memory pressure that forces the heap to expand, high GC overheads, and long GC pauses. In my last test, I executed the benchmarks with -XX:+PrintGCDetails and -XX:+PrintGCTimeStamps, to calculate the number of objects that are allocated and recycled per time unit. I executed JavaFX Balls in the 512 Balls mode to have a fixed effort per frame. All scores are normalized to as bytes-per-frame.

ProgramJavaFX 1.2JavaFX 1.3JavaFX 1.3           
JavaFX Balls82 Kb/frame75 Kb/frame0,33 Kb/frame
Strange Attractor10 Kb/frame5,75 Kb/frame 
GUIMark22 Mb/frame24 Mb/frame75 Kb/frame

Comparing JavaFX 1.2 to 1.3, in the first two tests the new release burns 43% less memory in the Strange Attractor benchmark - which barely does anything other than event handling, some math and writing to a raw int[]. So, this test shows that JavaFX 1.3 is more efficient, allocating half the temp objects to sit doing almost nothing. ;-) The JavaFX Balls test shows that 1.3 is also more efficient, 8% advantage, doing heavy animation with many nodes. So far, a nice incremental improvement.

GUIMark shows a small regression in JavaFX 1.3, but it's difficult to judge these results because the frame counts are very low and the animation engine is having to skip frames. Anyway, both allocation scores are extremely high, which certainly helps to understand the awful GUIMark scores of 1,81 fps and 2,81 fps: it's not just some dumb layout calculation algorithm; the system it allocating memory like there's no tomorrow, which is both wasteful in itself, and points to other internal inefficiencies.

Prism is the big winner though, pulling order-of-magnitude gains again. Prism's performance comes from a smarter architecture, and we can see another aspect of that here - the Prism animation engine allocates vastly less temporary objects. To be exact, it's under 0,4% of the Swing toolkit's allocation ratios for both JavaFX Balls and GUIMark, which is some insane amount of optimization. Well, other way to look at this is that the Swing toolkit is really broken for tasks like text rendering and complex layout.

The Java/Swing GUIMark scores 5,4Mb/frame, which makes it only ~4X better than JavaFX. The Swing code has no scene graph, it's all immediate-mode rendering, which saves some live memory. Still, a quick profiling session shows abundant allocation of temporary char[], int[] and byte[] arrays - a smoking gun for drawing and text code that needs to copy data into temporary buffers that are not reused. This provides an interesting argument against the common wisdom that scene graphs are less efficient than immediate-mode rendering. Truth may sometimes stand in the opposite side, because a scene graph is able to reuse buffers and other expensive helper objects across frames. My analysis of the Java/Swing GUIMark source code revealed very few allocation inefficiencies - creation of some constant Color and GradientPaint objects in the paint methods - and I fixed them all, but there was no impact in performance; the byte-wasters are definitely inside JavaSE's graphics and text APIs.

The GUIMark tests need some Full-GCs, except again for Prism. HotSpot Server will avoid Full-GCs even for the Swing toolkit, but that's because it sizes the heap more aggressively. Server's default starts at 64Mb but it stabilizes at ~68Mb for JavaFX 1.2 and ~90Mb for JavaFX 1.3; while HotSpot Client runs the program within its much smaller default heap size of 16Mb. That's one of the reasons why you don't want HotSpot Server for client-side apps. I could have made these numbers better, and probably gain some performance, with some manual tuning - but my execution rules for all RIA benchmarks include zero manual tuning. For GC in particular, the "ergonomics" feature of HotSpot must be good enough for client apps. For Prism, once again we have ideal behavior, both variants of HotSpot run the program with their respective default heap sizes.


My experience running all these testes was not 100% smooth. I've already reported the worst issues, with StrangeAttractor, but these were expected/deserved as I've relied on internal APIs.

JavaFX 1.3 is not 100% compatible with JavaFX 1.2. Check the JavaFX Migration Guide. This time around, we have very minor language changes.

  • The change to forward-reference behavior is very welcome (fixes a language design mistake; previous behavior produced code that didn't behave as expected by the programmer).
  • Binding expressions must now be pure (no side effects), a very welcome change - JavaFX Script has a light functional subset, and bound expressions are one place where enforcing pureness delivers great benefits.
  • The change of binding to the default lazy behavior is the same - temporal transparency is another important part of functional purism, and once again it allows the compiler to be extra smart; you just need to make sure that your program doesn't depend on eager behavior, e.g. using a bound expression to invoke a method that must be run at initialization time.
  • The new on invalidate clause and isReadOnly() synthetic method should not break any code, except perhaps if you use these names as identifiers.

Then we have some breaking API changes; most are very subtle issues like changed access modifiers, or changed algorithm for preferred size calculation. Some larger changes in layouts, controls and charts mean that apps having complex UIs, e.g. with nontrivial layout code, should be the most affected. Nothing in the lists above affected any of my tested programs.

When testing Prism, I've had some extra trouble with my usage of non-public APIs. The code and properties that I use to disable the animation engine's "pulse" (that caps the number of frames per second) does not work on Prism. Setting the property com.sun.scenario.animation.pulse to 1000 has no effect on Prism, and while I've found Prism's properties (check prism-common.jar /, there is no equivalent "pulse" property. There is a property prism.vsync that I can disable, but the only result is that instead of a perfect 120fps rate (on my system/monitor at least), Prism will use other mechanisms (just like the Swing toolkit) to approach the same 120fps target. I will appreciate any hint if you know better.

Bye-bye Swing Bridge

Beware too of the javafx.ext.swing package, as it is completely unsupported on Prism - will bomb with a NoClassDefFoundError. This is not going to change; Prism cannot support legacy Swing controls - in fact, Prism configures the JVM run run in AWT Headless mode, so many AWT/Java2D/Swing classes will fail to work even if you create them directly. Prism does its own access to video hardware, creation of top-level windows, has its own Event Dispatch Thread etc., so it's just not possible to allow the equivalent stack from JavaSE to run simultaneously. If you've been relying on the javafx.ext.swing package to easily port legacy Swing code or to compensate for missing JavaFX controls, be warned that in some future release, Prism will most certainly become the only supported toolkit, and the JavaFX/Swing bridge will be gone for good. (I suppose that he first release with production-quality Prism will make it default but still support the Swing toolkit; the latter could be removed in another release or two. But it will be removed. Won't likely get any enhancements or even fixes in this EOL period, either.)

This also explains why the JavaFX team didn't do a better job in that bridge, not implementing some features requested by Swing programmers, e.g. embedding JavaFX components inside Swing apps - I suppose they could have implemented these features, but that would just push more people to do quick Swing/JavaFX ports or hybrids, that would hit a brick wall in a future JavaFX release. It's not that Sun was evil, refusing to support Swing developers and their assets of code, tools and components. Now that 1.3 already offers a decent set of controls - ok, at least considering the experimental ones, and third-party like JFXtras's - and has really powerful and easy building blocks to create new controls, I'll warn any adopters to consider the Swing bridge mostly as a compatibility feature... for JavaFX 1.2 apps that already used Swing controls. Not as something that should be used for development of any new, JavaFX 1.3 app.

I believe though, that it should be possible to create a new compatibility layer: a Swing-over-JavaFX implementation, where the Swing controls and higher-level API are implemented on top of the JavaFX scene graph. The SwingWT project does something similar (Swing over SWT), so my suggestion is probably possible - but it's also very likely a pretty big effort. For one thing, this could be justified as a transitional solution for the NetBeans RCP platform.


In this blog I've focused only in a few areas of JavaFX 1.3, mostly performance and Prism, and still with a limited set of benchmarks. I didn't even start looking at the new controls or any other changes, and 1.3 has quite a few new & enhanced features. But performance is critical, it can spell the success or the doom of a platform. JavaFX was already the RIA toolkit to beat in some performance aspects - although mostly due to the superiority of its underlying VM, that (even with the Client version of HotSpot) is second to no competitor's. Java's technology for JIT compilation, GC etc., just rules. But JavaFX it still needs to catch up in some important issues, remarkably startup time and footprint. This requires continuous improvements in both the JavaFX and the JavaSE runtimes. JavaFX 1.3 adds some nice incremental improvements across the board, but it still carries the weight of the legacy AWT/Java2D/Swing toolkit, plus the limitations of JavaFX's first-generation animation package.

What you really want is Prism, which puts some impressive results here, in every performance aspect from speed to loading time and footprint. Prism wins by a landslide the previously-embarrassing GUIMark test; enables upcoming advanced features like additional 3D support; and there's rumor it will make zero-calorie french fries too.  So, when is Prism shipping? I guess that will be JavaFX 1.3.1 in June. Prism was originally supposed to ship in production quality in 1.3; its current EA release looks surprisingly good (although my tests are admittedly very limited); and JavaFX TV's FCS depends on it. This certainly shouldn't freeze JavaFX adopters again until the next release; yes the next one will be even better, but even without Prism the JavaFX 1.3 release is already a big step forward, greatly expanding the number of applications that JavaFX could serve very adequately.