On How to Speed up FXML Performance
I'll make this answer community wiki, if anybody else has further ideas, please edit it and add them.
- One should NOT use the static FXMLLoader.load() but should instead create an instance of FXMLLoader and reuse that one using the instance loader.load() method. The reason is that the FXML-Loader caches, e.g. class lookups, and hence is faster on loading the next FXML-File.
- Use a tool to compile the FXML to Java, such as Tom Schindl's FXML compiler or the NetBeans FXML to Java converter.
- Don't load any more FXML than you need to at any given time, e.g. if you aren't going to be displaying it right now, don't load it.
- Load the FXML in a background thread (doesn't work for some control types, e.g. Tooltip, in Java 8).
- Load an initial login or splash screen first and then load the rest of the FXML while the splash or login screen is displayed. I load FXML in some apps after the credentials are accepted at the login screen.
- Reduce the complexity of your application UI by removing unnecessary nodes.
- Ensure you aren't doing unnecessary work (e.g. reading a database) on the JavaFX UI thread in the initialize methods of your controllers.
- The FXMLLoader.load() documentation in JavaFX 8 includes a reference to FXML templates, but I don't think that was ever implemented, so maybe it won't help you.
- I heard mention that referring to static methods from FXML is slow.
- Use the latest development version of JavaFX.
- Once you have loaded a node hierarchy from FXML, reuse the hierarchy later rather than throwing it away and loading a new one (e.g. if you have a dialog window with contents constructed using FXML, when the user closes the dialog, just hide it and when you need to show a similar dialog again, just show the hidden dialog rather than constructing a whole new dialog and scene graph).
Reflection is why FXML is Slow
I think the key reason the Java 8 FXML implementation is slow is that it relies so heavily on reflection and reflection is slow as described in the reflection tutorial:
Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.