Skip to main content

First, long look at JavaFX 1.3 (and Prism)

Posted by opinali on May 3, 2010 at 11:34 AM PDT

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).

Test JavaFX 1.2
(Client)
JavaFX 1.2
(Server)
JavaFX 1.3
(Client)
JavaFX 1.3
(Server)
JavaFX 1.3
(Prism/C)
JavaFX 1.3
(Prism/S)
1 Ball 999 fps 1000 fps 1000 fps 1000 fps    
16 Balls 998 fps 998 fps 1000 fps 1000 fps    
32 Balls 986 fps 998 fps 998 fps 998 fps    
128 Balls 490 fps 636 fps 608 fps 666 fps    
512 Balls 90 fps 108 fps 124 fps 151 fps    
@ 60 fps 642 Balls 699 Balls 815 Balls 878 Balls 817 Balls 1.173 Balls
@ 200 fps 285 Balls 358 Balls 366 Balls 428 Balls    
Effect, 1 Ball 666 fps 666 fps 666 fps 972 fps    
Effect, 16 Balls 150 fps 165 fps 162 fps 220 fps    
Effect, @ 60 fps 44 Balls 47 Balls 45 Balls 66 Balls 377 Balls 642 Balls
Effect, @ 200 fps 12 Balls 13 Balls 12 Balls 14 Balls    
2D, @ 60 fps 70 Balls 70 Balls 68 Balls 71 Balls 96 Balls 105 Balls
2D, @ 200 fps 18 Balls 20 Balls 20 Balls 20 Balls    
2D+Eff, @ 60 fps 27 Balls 28 Balls 25 Balls 26 Balls 75 Balls 82 Balls
2D+Eff, @ 200 fps 7 Balls 7 Balls 7 Balls 7 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.

Test JavaFX 1.2
(Client)
JavaFX 1.2
(Server)
JavaFX 1.3
(Client)
JavaFX 1.3
(Server)
MainListDouble 74 fps 96 fps 80 fps 94 fps
MainSeqDouble 62 fps 77 fps 65 fps 78 fps
MainFloatRaw 144 fps 166 fps 162 fps 250 fps
MainListDouble3D 62 fps 78 fps 50 fps 64 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.

Program JavaFX 1.2
(Client)
JavaFX 1.2
(Server)
JavaFX 1.3
(Client)
JavaFX 1.3
(Server)
JavaFX 1.3
(Prism/C)
JavaFX 1.3
(Prism/S)
GUIMark 1,81 fps 2,22 fps 2,81 fps 4,44 fps 78 fps 120+ 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.

Program JavaFX 1.2 JavaFX 1.3
HelloWorld 2 classes, 2.726 bytes 2 classes, 2.579 bytes
JavaFX Balls 19 classes, 95.19 bytes 19 classes, 117.005 bytes
Strange Attractor 62 classes, 563.769 bytes 62 classes, 427.992 bytes
Interesting Photos 53 classes, 238.902 bytes 46 classes, 431.741 bytes
GUIMark 9 classes, 93.841 bytes 27 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.

Program JavaFX 1.2 JavaFX 1.3
(Swing)
JavaFX 1.3
(Prism)
HelloWorld 1.660 classes 1.717 classes 984 classes
JavaFX Balls 1.847 classes 1.885 classes 1.111 classes
Strange Attractor 1.894 classes 1.996 classes 1.201 classes
Interesting Photos 2.095 classes 2.032 classes 1.193 classes
GUIMark 2.033 classes 2.207 classes 1.360 classes
AWT HelloWorld 1.050 classes
Swing HelloWorld 1.206 classes
Swing GUIMark 1.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 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).

Program JavaFX 1.2 JavaFX 1.3 JavaFX 1.3
(Prism)
HelloWorld Heap: 628K
Perm: 2.716K
Heap: 671K
Perm: 3.318K
Heap: 421K
Perm: 3.199K
JavaFX Balls Heap: 1.085K
Perm: 3.685K
Heap: 801K
Perm: 4.161K
Heap: 635K
Perm: 3.779K
Strange Attractor Heap: 13.876K
Perm: 3.764K
Heap: 18.448K
Perm: 4.306K
Heap: 17.629K
Perm: 3.957K
Interesting Photos Heap: 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.

Program JavaFX 1.2 JavaFX 1.3 JavaFX 1.3
(Prism)
JavaFX Balls 82 Kb/frame 75 Kb/frame 0,33 Kb/frame
Strange Attractor 10 Kb/frame 5,75 Kb/frame  
GUIMark 22 Mb/frame 24 Mb/frame 75 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.

Porting

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 / com.sun.prism.pk.PrismSettings), 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.

Conclusions

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.

Comments

"Bye-bye Swing Bridge"

Whoa... this has not been discussed or mentioned anywhere else as far as I know... This really is the final two fingers to all the Swing developers out there... Most Swing devs and large Swing projects are the biggest opportunity for JavaFX but the powers that be seem to think its greenfield toy/app development - wake up! Like a lot of other Swing developers I know, we were planning to migrate a large Swing app to JavaFX - and were waiting on 'real' controls to appear in FX (sort/filter table etc) - so for now the only way was via embedding swing JTable etc.... also for other projects embedding JavaFX parts into existing Swing projects would also have been a great way to get existing developers down the JavaFX path... So this move really puts a wedge between Swing and JavaFX. this along with the JWebPane fiasco for us simply means ... bye bye JavaFX

Bad communication?

See my own comments, I may have made some too-quick conclusions, it's possible that Oracle will offer some good migration path and there's some evidence that they are committed to it.

On the other hand, Oracle is certainly mismanaging its community communication very badly. I shouldn't have to dig up that quote "there are plans to officially support embedding javafx in a swing app..." from some non-official extensions site like JFXtras. This should be written in large, friendly letters, somewhere at javafx.com, and complete with a good roadmap (specific features X specific releases of JavaFX and NetBeans). A quick google search "Swing site:javafx.com" turns out no such information, just a handful of articles covering the existing Swing bridge. (The very best of these resources is just a link to an external page, Amy's blog.)

Until Oracle opens up a bit, the FUD (including accidental one like mine) will spread, and Swing developers like you will have this "final two fingers" feeling and with reason. But this is good subject for another blog - the state of JavaFX's licensing, development model, and transparency...

Swing integration is absolutely needed.

Beside the "featureitis" the most common mistake of techies is to compare certain parameters (in this case rendering speed a.o.) and to use this as the argument to identify the "best" technology they bet their heard-blood on. Often ignoring all non strictly technical parameters. It is always not the best technology that gets adopted but the one that is similar to what people already know. It only has to be fairly fitting from a technical point of view. Not the best singer sells most records! There are several show stopper arguments connected with JavaFX if it can't be integrated with Swing.

1. Swing is the only Java Desktop technology that has any kind of credibility. There are many developers for this technology and many open positions. Swing was once even the most common GUI technology in IT-industry with a large ecosystem. It lost since then, but look for example at Indeed.com for "Java Swing" positions and you will see what I mean. (To get a feeling compare to "WPF" and "JavaFX"). If there is no gradual passage to JavaFX and you make a sudden change in the technology, you will loose many Swing developers and whether JavaFX will ever be as big as Swing was, is doubtful. More probably Java desktop will get a hard hit from that and will never have any chance again.

2. Many, many applications have been written with the Netbeans framework. And this is Swing. It has to be possible to write new modules for an existing application that integrate with the existing ones. Much more often an existing code will be expanded than a new project started.

3. Swing has the possibility to write applications that look and feel very native and that can be sold to the customers as native feeling applications for their platform. Look at the wonderful implementation of Swing by Apple. With JavaFX, to my knowledge, it is not possible to create a native looking application. They sit on your desktop as pink aliens. This is unusable for many applications that Swing has been used for. With no integration of JavaFX you loose all the hard years of tuning and refinement of Swing. We were already at the level of discussing single pixels that were different in Swing as compared to native Look and Feel. All lost.

4. There has to be a Java API for the JavaFX functionality. Beside that I prefer universal languages, I find it a bad idea to memorize a special language for GUI programming. The declarative code is in my opinion not clearer than Swing code for any non trivial GUI. But beside that, Java is a platform in these days and the APIs of this platform should be callable from other platform languages like Java or Scala if you prefer them. The JavaFX concept as it is, is complete inconsistent to the concept of the Java platform, as GUI programming needs to be done in JavaFX.

5. Custom Java Webstart/Swing applications were the only widely used use-case for Java GUIs. Sun/Oracle has no other platform such as Smartphones were a GUi technology is needed. JavaME is on its way out, Android has its own concept as do iPhone and Windows Phone 7. No room for a Sun/Oracle GUI technology. At the Web HTML5 is pushed by the main vendors Microsoft and Apple. And interactive TV I see as a joke, as TV is for turning your brain off. No GUI technology is needed for deactivated brains.

To sum this up: JavaFX should enable drawing on a JPanel in your Swing application. It should be possible to use JavaFX scripting language to declaratively describe Swing GUIs. It should be possible to use JavaFX nodes in Swing containers e.g. for movie display. Swing APIs need to be advanced and integrated with JavaFX as tightly as possible. Otherwise I predict the complete end of Java at the desktop.

"Featuritis" and speed

Now replying on that part of your message: notice that my blog didn't cover any new feature (functionality) and it didn't focus solely on speed either, but rather in overall performance, including factors that are more critical for client-side apps like footprint, startup costs, and memory management. It is widely perceived that one of JavaFX's major challenges - to compete with HTML5, Flex, Silverlight - is these "other" performance aspects (as well as some additional deployment issues). To replace corporate Swing apps that are successful even with 10-second loading times and 200Mb heaps, I agree that all these performance enhancements are secondary, JavaFX must only not be worse.

Remember also, that JavaFX's graphics/animation engine is critical for its whole GUI performance. Say you have a big Grid stuffed with complex data, custom item rendering, embedded components etc. (FX doesn't have a Grid yet, but it's on the works.) Now say you want to drag a column to reorder it. This will be performed like everything else in FX, by the scenegraph-based pipeline. And you will likely want to throw in some decoration that's trivial in JavaFX, e.g. a drop-shadow and/or transparency of the dragged column, then you want to have good animation performance. Ditto if you want to fast-scroll through a complex document - GUIMark is a good test of that: it measures text output, layout and composition, much like a rich-text editor or other "document-like" code. If you're not into games or graphics/media-centric programs you can disregard tests like Bubblemark or Strange Attractor as not representative of "real-world apps"; but GUIMark certainly is much more representative.

Finally, JavaFX is similar to the stuff people already know - Java. Like I commented before, it's a piece of cake to learn and to integrate with massive amounts of existing Java assets (excluding visual ones that depend on AWT/Java2D/Swing, admittedly). If JavaFX was not available, many Java developers would have to defect to options that are much more different than Java, like Flex/AIR and Silverlight - and it seems many developers and companies have already done so, regardless of the much larger programming language gap or zero reuse of Java code. If you are happy with Swing, I agree that JavaFX may look like an unnecessary learning curve and uncompatible change, to solve a no-problem. But not everybody is happy with Swing, most remarkably for internet deployment (JRE 6u10+ was certainly not good enough to bring the promised resurrection of Applets and JAWS). IMO, JavaFX doesn't win over Swing only in graphics speed; it wins - at least potentially, assuming mature tools etc. - in productivity, maintainability, portability, and features.

Application of JavaFX

I really do not want to troll, but in my opinion the only, but very important, application for Java on the desktop are those rich, web-started enterprise applications.
This is the major story of Java GUIs. And it is an important one, so Sun/Oracle should do everything to refine and polish it (especially Webstart need much more work). In enterprise it is a major feature to keep everything backward-compatible!
Everything else on the GUI side will be pure Web technology, that is HTML5. There will be no Flex or other "rich web technology" in the future and Silverlight will be the corresponding enterprise client technology of the .NET crowd. (With the difference that they have a smartphone platform)
Argument: The major vendors of client side operating systems/computers Microsoft and Apple said so. And it makes sense because HTML5 is an open and good enough solution that is similar to what all developers already know. The open source people can also follow that path and everybody (except Adobe) will be happy with it. Including consumers. Tools will be developed by Adobe (when they stopped clamoring because of Flex) and many others to generate HTML5 content in the same way Flex content is generated today.
Sorry to say that, but in my opinion there is no place for JavaFX as a web technology. Therefore Sun/Oracle, please modernize the Swing APIs and integrate it seamless with the JavaFX functionality. Offer JavaFX script as an alternative for Swing programming if people want it, but continue to built on the mature Swing foundations.
And for smartphones and JavaFX I see no other solution than that Larry drinks much german beer with his buddy Steve and something moves :-) Otherwise, Sun/Oracle, save your energy for the enterprise scenario.

I agree that I did no good contribution regarding the interactive TV so let me have another try: If we assume that interactive TV would be something that people would want, what would you do as a manufacturer of TV sets to implement it? I would take the open source, high quality Webkit and a JavaScript engine and compile it for my device. They are small enough to run in smartphones, so a TV set should have no problem with them either. Problem solved, you have unlimited content, developers and tools. No place for JavaFX to thrive either, limiting "the screens of your life" to the enterprise desktop.

Not mutually exclusive

I agree that rich, web-started EE apps are a very important Java GUI story and one that FX should preserve. The worst thing Oracle can do now is to lose even the beach head that Sun managed to defend for desktop Java. Swing developers must be seduced by FX's advantages (and helped by some migration path!), not alienated by Swing's abandon - that will certainly move people entirely off JavaSE.

On the other hand, I don't agree that a GUI platform cannot cover several usage scenarios. WebStart (as well as plugin2, and general JRE deployment) is still being continually enhanced (try 6u21-b03), to the benefit of both FX and Swing, and both internet and intranet deployment.

Backwards compatibility is indeed a necessity, but it cannot be an impediment for innovation. It's already bad enough that the Java language can't get any major enhancement that requires even minor compatibility breaking (that would be the case with reified generics; some critics still don't understand that it was impossible to do anything better than Java5's generics without some compatibility compromise). JavaFX brings Java to the 21st century in GUI technology - other GUI platforms that have made this transition were also forced to leave the past behind, e.g. Microsoft's WPF&Silverlight and the underlying graphics stack in Vista and Win7. Swing cannot be fixed to be fully GPU-accelerated, or to be scenegraph-based. The Java programming language cannot be fixed to have a powerful binding mechanism (the proposed Beans Binding for Swing was a big kludge compared to the powerful, seamless binding of JavaFX Script). How many additional layers of half-backed, inefficient, inelegant, convoluted patches do you want to pile on Java and Swing?

HTML5 is good enough to build better web sites/apps than the current web sites/apps; but it is clearly not good enough for many desktop apps. Even the über-web-centric Google knows that, as they admit when they start working on things like Native Client and Android's native SDK; their ChromeOS system will not be pure-web either, jst the opposite, I expect that it will benefit massively of things like PNaCl. Yeah, that's Google - of all companies - telling you that HTML5 is not good enough. They have the best JavaScript interpreter (V8 has just got another amazing 30% speed-up in the latest Chrome-dev), they have other state-of-the-art pieces like overall webbing speed and the best security and process/resource management; and it's still not good enough, and won't be any time soon.

As for digital TV, I'm not an expert either, but I know (being a Brazilian) that our government officially adopted JavaDTV, including LWUIT, as part of its official Digital TV platform "Ginga". This is of course not JavaFX TV yet, but it's Java, and FX-TV is not really a replacement for all those DTV specs, it's in a higher level. Anyway this market cannot be ignored - modern TV sets have relatively powerful computing capabilities; they need menus, cheap games and other simple embedded apps, and on top of that you can have installable content, and cable/satellite tuners and set-top box appliances where a standard/official platform is not always a big requirement. I found on the internet (about JavaDTV / Ginga) that "Sun had fixed the royalties value at USD 0.39 cents per piece of equipment", this looks cheaper than maintaining your own WebKit-based platform. Other players are also trying to enter this market, e.g. Microsoft Silverlight.

Good points

1, 2. Check my previous comment, it seems they are indeed planning some migration path better than "rewrite everything" or "FX is only good for brand-new projects with no legacy". But we have to wait, and unfortunately, wait in the dark as Oracle's ability/willing to communicate their plans in this area has been quite bad so we can just speculate at this point.

3. I agree that native LAF is critical to many apps; but FX 1.3+ has such powerful styling capabilities that I can hope some set of platform-specific LAF options are just around the corner. Once again, we can only wait and see the next developments.

4. You won't have that, and I don't see the issue here - JavaFX Script is really easy to pick up. Much easier (say) than JavaScript, which 90% of all Java developers have to learn in some extent for web apps. GUI-specific DSLs are nothing new, there's a huge maze of these for the web (although I hope JSF will consolidate a lot), look also at Groovy's SwingBuilders, or Flex / Silverlight / Android all of which force you to write most of your GUI in some big XML language (all of them IMHO, horrendous compared to the seamlessness of JavaFX Script - which doubles as programming langage, GUI description language, AND and excellent vector-graphics language - nothing short of amazing for a single syntax). I will only complain that JavaFX Script still lacks a native map data type, to be considered a reasonable general-purpose programming language of its class, so we don't have to mix in some Java classes for the business logic.

5. Agreed with the status of mobile (see my other, previous comment), but not with JavaFX TV, in this part your comments are not any better than trolling so I won't care to answer.

Nice Read

Really nice write up, thx. Looking forward to the playing with Prism as it seems to be going in the right direction. One thing I'm really curious about is that you mention Prism runs in headless mode which sounds great but how will it work as an applet? will you still embed on awt or is there some new special mode for prism to run in an applet? thx

Nothing unusual for applets

Prism should run applets; remember that with JavaFX you don't use the java.applet package directly, it's the JavaFX runtime that provides an Applet implementation to interface with the browser / plugin2 / JAWS, so they can provide an implementation that does not depend on AWT non-headless. Or, they can just dump java.applet altogether.

An excellent review,

An excellent review, Osvaldo.

I'm puzzled about the dropping of Swing compatibility. I understand the rationale, but this could be a wrong evaluation of pro/cons from Oracle. There's such a large spread of Swing stuff in the enterprise that it's unlikely that one can introduce JavaFX if he can't do in incremental way. It's also to be said that most of current adopters of Swing don't have any reason for moving to JavaFX, so Oracle is perhaps focusing on optimizing the thing for new segments. 

Too bad there are no news yet about JavaFX Mobile new endorser. Time is expiring.

On JavaFX Mobile

I expect Oracle to announce something decent in June when JavaFX 1.3.1 ships, presumably with the FCS of Prism, Mobile & TV.

Looking at the JIRA is no help, they keep developing this under closed and firmly-shut doors - even for the Desktop runtime, the JIRA issues and roadmaps are not 100% public and transparent. It doesn't help (or perhaps it does?) that the entire mobile space is under enormous turmoil - it's premature to state things like "the iPhone has won"; Android is growing in breakneck speed, HP may be able to turn out a great webOS product line, even Microsoft may redeem WinMob with a good v7.x and mobile Silverlight, Flash 10.1 Mobile will ship soon... there's also the big sleeping giant in Helsinki, these guys could wake up some day with a coherent strategy. The whole tablet market is just in the diapers. If the FX teams delivers a great mobile implementation, I'm sure they would carve out a few opportunities. (The JavaStore guys have also been very silent in the last few months; it's either D.O.A. or they are planning some big relaunch.)

May have jumped the gun on Swing...

...on the other hand, a good blog needs some forward-looking, polemic statements. ;-)  JavaFX 1.3 is still missing at least one major control that's not even in the preview package (Table/Grid), I hope we don't have to wait two major releases for that (initial release in 1.4 but with preview status, production release in 1.5) but can't be ruled out either. I'm sure the Swing bridge will be kept at least until FX has a strong offering of "native", SG-based controls and other basics.

The JFXtras project has a JXScene component that allows embedding FX into Swing; it's coarse-grained integration but that's much better than nothing. Only now I noticed in its page: "The next release of JavaFX will make this much harder to accomplish as it will no longer be dependent on AWT/Swing, the underlying graphics engine will be replaced. However there are plans to officially support embedding javafx in a swing app and the next release codenamed Soma will have some pre requisite work done on that matter." This is good news, and matches my suggestion for adding some compatibility layer, probably requiring the replacement of the lower layers of Swing. But it hints that future compatibility efforts can focus in the opposite of the current bridge -- embedding new FX code into Swing apps, not Swing components into FX apps. And it makes sense, it's probably a better plan for incremental evolution of existing Swing applications.

Adoption is everything. Somebody complained to me that he could use Flex but not JavaFX in some corporate/government projects due to licensing issues; this kind of thing must also be sorted out. And the big baggage of Swing code from Oracle itself is another important factor, like I pointed in the blog (NetBeans etc.) - providing some great Swing->FX migration/coexistence path would be critical, even if just as a self-serving effort. My hunch is that Sun didn't do it yet only due to absolute lack of resources, we can't forget that Sun was still hemorrhaging money and engineers a very few months ago; now under Oracle they should be breathing better. In an ideal world, Oracle would provide an alternative implementation of all old APIs - AWT, Java2D & Swing - that drops the lower-level layers (AWT peers, Java2D hardware pipelines) and just call into FX instead. This would have some tricky parts; AWT is very hairy, and Java2D would probably have to software-render everything into memory surfaces that FX would then plaster over its surfaces. Applications that depend too much on internals, like fine behavior of AWT events, might not work. Performance could suffer - but that's a minor point, I'd expect this to be used for "standard" corporate GUIs that use controls heavily but not much custom rendering, and certainly not games or advanced graphics apps like blueMarine.