# JavaFX Graphics Performance



## Innovation (31. Jan 2014)

Hallo erst mal,

ich habe eine Frage und ein Problem:

1.) Ist JavaFX im vergleich zu Java2D schneller. Ich meine jetzt beim Zeichnen von BufferedImages,
beim zeichnen von Kreisen, etc?

2.) Ich habe hier folgende, simplen Programm Code:

```
public class JavaFXPerformanceTest extends Application {

	@Override
	public void start(Stage primaryStage) {
		Group root = new Group();
		Scene scene = new Scene(root, 300, 250, Color.BLACK);

		final Canvas canvas = new Canvas(250, 250);
		final GraphicsContext graphics = canvas.getGraphicsContext2D();

		root.getChildren().add(canvas);
		primaryStage.setTitle("JavaFX Performance");
		primaryStage.setScene(scene);
		primaryStage.show();

		Platform.runLater(new Runnable() {
			@Override
			public void run() {
				int counter = 0;
				while (counter < (10_000 * 1000)) {
					long start = System.currentTimeMillis();
					graphics.clearRect(0, 0, graphics.getCanvas().getWidth(), graphics.getCanvas().getHeight());
					for (int i = 0; i < 10_000; i++) {
						graphics.setFill(Color.GREENYELLOW);
						graphics.fillRect(Math.sin(counter++) * 100.0 + 100, 10, 25, 25);
					}
					long end = System.currentTimeMillis() - start;
					System.out.println(end);
				}
			}
		});
	}

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

Wie man hier sieht, zeichne ich 1000 mal 10_000 Rectangles auf den Bildschirm und geben dann aus,
wie lange für den Zeichenvorgang gebraucht worden ist.

Folgende, "merkwürdige", Ausgabe wurde produziert:

```
16
26
19
23
28
33
40
48
47
66
63
73
74
80
90
96
111
116
127
167
157
149
165
170
180
195
193
197
215
226
233
251
248
254
```
Wie man sieht, wird die Zeit pro Zeichenvorgang immer länger.

Könnte mir einer sagen, warum? ???:L

Würde mich sehr freuen, wenn mir jemand diese beiden Fragen beantworten könnte.

Mit freundlichen Grüßen,
 - Daniel


----------



## dzim (31. Jan 2014)

Würde es mit morgen vielleicht mal anschauen. Wenn ich Lust haben sollte..  
Ansonsten erst Montag. Der code sollte aber sehr Ähnlich sein, von daher sehe ich da kein Problem...


----------



## dzim (2. Feb 2014)

Hi. Zwei Probleme:
1) Du rechnest auf dem Hauptthread (UI-Thread) und schickst es per Platform#runLater wieder dort hin - wenig Zielführend.
2) Dein counter++ ist - glaube ich zumindest - auch wenig hilfreich.

Habe es einmal angepasst und ich glaube, es macht jetzt das, was es soll.
Pro Durchlauf gehen dabei meist (aber nicht immer) maximal niedrige zweistellige Zeiten drauf:


```
public class PerfTest extends Application {

	@Override
	public void start(Stage primaryStage) {
		Group root = new Group();
		Scene scene = new Scene(root, 300, 250, Color.BLACK);

		final Canvas canvas = new Canvas(250, 250);
		final GraphicsContext graphics = canvas.getGraphicsContext2D();

		root.getChildren().add(canvas);
		primaryStage.setTitle("JavaFX Performance");
		primaryStage.setScene(scene);
		primaryStage.show();

		Thread t = new Thread(new Runnable() {
			@Override
			public void run() {
				int counter = 0;
				while (counter < (10_000 * 1000)) {
					long start = System.currentTimeMillis();
					Platform.runLater(new Runnable() {
						@Override
						public void run() {
							graphics.clearRect(0, 0, graphics.getCanvas()
									.getWidth(), graphics.getCanvas()
									.getHeight());
						}
					});
					for (int i = 0; i < 10_000; i++) {
						final int _i = counter;
						Platform.runLater(new Runnable() {
							@Override
							public void run() {
								graphics.setFill(Color.GREENYELLOW);
								graphics.fillRect(Math.sin(_i) * 100.0 + 100,
										10, 25, 25);
							}
						});
					}
					long end = System.currentTimeMillis() - start;
					System.out.println(end);
					counter++;
				}
			}
		});
		t.start();
	}

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

Solche Operationen also immer in einem *anderen* Thread durchführen und von dort via Platform#runLater zurück zum Hauptthread schicken.


----------

