Warum ist "Stage # show" so langsam und was kann getan werden, um es zu beschleunigen?

In JavaFX wird eine Stufe zum ersten Mal mit @ angezeigStage#show es dauert lange. Ich spreche nicht über die Zeit, die zum Laden von FXML benötigt wird (was insgesamt ein anderes Problem darstellt), sondern über die Zeit, die zwischen dem Aufrufen von @ benötigt wirStage#show und der zurückkommende Anruf (und das Fenster, das dem Benutzer angezeigt wird).

Ich habe diese Beispielanwendung erstellt, die eine zufällige Szene mit ein paar Registerkarten, Rasterfenstern und Tabellenansichten erstellt. Dann mal, wie lange es dauert, @ aufzurufeStage#show:

package sample;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.util.Random;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        primaryStage.setTitle("Speed test");
        primaryStage.setScene(createScene(3, 3, 6, 8));
        long start = System.nanoTime();
        primaryStage.show();
        long end = System.nanoTime();
        System.out.println("Total seconds: " + ((double) (end - start)) / 1000000000);
    }

    private Scene createScene(int tabs, int rows, int columns, int tableColumns) {
        TabPane tp = new TabPane();
        for (int t = 0; t < tabs; t++) {
            GridPane gp = new GridPane();
            for (int r = 0; r < rows; r++) {
                for (int c = 0; c < columns; c++) {
                    gp.add(getRandomControl(), c, r);
                }
            }
            TableView<Object> tv = new TableView<>();
            for (int i = 0; i < tableColumns; i++)
                tv.getColumns().add(new TableColumn<>(getRandomString()));

            VBox vb = new VBox(gp, tv);
            tp.getTabs().add(new Tab(getRandomString(), vb));
        }
        return new Scene(tp);
    }

    private final String[] randomStrings = new String[]{
            "foo",
            "bar",
            "baz",
            "lorem",
            "ipsum",
            "dolor",
            "sit",
            "amet",
            "adipiscing",
            "elit",
            "morbi",
            "quis",
            "tempus",
            "justo",
            "faucibus",
            "justo",
            "risus",
            "nec",
            "commodo",
            "sem",
            "congue"
    };

    private final Random random = new Random();

    private String getRandomString() {
        return randomStrings[random.nextInt(randomStrings.length)];
    }

    private Control getRandomControl() {
        switch (random.nextInt(4)) {
            case 0:
                return new Label(getRandomString());
            case 1:
                return new TextField();
            case 2:
                return new PasswordField();
            case 3:
                ComboBox<String> cb = new ComboBox<>();
                cb.getItems().addAll(randomStrings);
                return cb;
            default:
                return null;
        }
    }


    public static void main(String[] args) {
        launch(args);
    }
}

Meine Ergebnisse variieren natürlich, aber sie sind immer um die 1,2 Sekunden, was nicht viel klingt, aber sicherlich bemerkbar ist und nicht zu viel erwartet wird, wenn man bedenkt, dass meine Maschine in einem Bruchteil dieser Zeit vergleichsweise komplexe Benutzeroberflächen lädt ( solange sie nicht in JavaFX geschrieben sind, ist das).

So ist meine Frage - was verursacht diese schlechte Leistung? Gibt es einige Tricks oder Hacks, um diese Zeit zu minimieren, ähnlich wie beim Beschleunigen des FXML-Ladens?

Antworten auf die Frage(0)

Ihre Antwort auf die Frage