Skip to content

Commit 83eb0a7

Browse files
committed
8193445: JavaFX CSS is applied redundantly leading to significant performance degradation
Reviewed-by: kcr, dgrieve
1 parent 798afbc commit 83eb0a7

2 files changed

Lines changed: 132 additions & 0 deletions

File tree

modules/javafx.graphics/src/main/java/javafx/scene/Node.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9415,6 +9415,13 @@ final void reapplyCSS() {
94159415

94169416
if (cssFlag == CssFlags.REAPPLY) return;
94179417

9418+
if (cssFlag == CssFlags.DIRTY_BRANCH) {
9419+
// JDK-8193445 - don't reapply CSS from here
9420+
// Defer CSS application to this Node by marking cssFlag as REAPPLY
9421+
cssFlag = CssFlags.REAPPLY;
9422+
return;
9423+
}
9424+
94189425
// RT-36838 - don't reapply CSS in the middle of an update
94199426
if (cssFlag == CssFlags.UPDATE) {
94209427
cssFlag = CssFlags.REAPPLY;
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
package test.javafx.scene;
27+
28+
import javafx.application.Application;
29+
import javafx.application.Platform;
30+
import javafx.geometry.Insets;
31+
import javafx.scene.Scene;
32+
import javafx.scene.layout.HBox;
33+
import javafx.scene.layout.BorderPane;
34+
import javafx.scene.text.Text;
35+
import javafx.stage.Stage;
36+
import javafx.stage.WindowEvent;
37+
38+
import java.util.concurrent.CountDownLatch;
39+
import java.util.concurrent.TimeUnit;
40+
41+
import test.util.Util;
42+
import junit.framework.Assert;
43+
import org.junit.Test;
44+
import org.junit.AfterClass;
45+
import org.junit.BeforeClass;
46+
import static org.junit.Assert.assertTrue;
47+
48+
/**
49+
* This test is based on the test case reported in JDK-8209830
50+
*
51+
* Redundant CSS Re-application was avoided in JDK-8193445.
52+
* It results in faster application of CSS on Controls (Nodes). In turn,
53+
* resulting in improved Node creation/addition time to a Scene.
54+
*
55+
* The goal of this test is *NOT* to measure absolute performance, but to show
56+
* creating and adding 500 Nodes to a scene does not take more than a
57+
* particular threshold of time.
58+
*
59+
* The selected thresold is larger than actual observed time.
60+
* It is not a benchmark value. It is good enough to catch the regression
61+
* in performance, if any.
62+
*/
63+
64+
public class QuadraticCssTimeTest {
65+
66+
private static CountDownLatch startupLatch;
67+
private static Stage stage;
68+
private static BorderPane rootPane;
69+
70+
public static class TestApp extends Application {
71+
72+
@Override
73+
public void start(Stage primaryStage) throws Exception {
74+
stage = primaryStage;
75+
rootPane = new BorderPane();
76+
stage.setScene(new Scene(rootPane));
77+
stage.addEventHandler(WindowEvent.WINDOW_SHOWN, e -> {
78+
Platform.runLater(() -> startupLatch.countDown());
79+
});
80+
stage.show();
81+
}
82+
}
83+
84+
@BeforeClass
85+
public static void initFX() throws Exception {
86+
startupLatch = new CountDownLatch(1);
87+
new Thread(() -> Application.launch(QuadraticCssTimeTest.TestApp.class, (String[]) null)).start();
88+
89+
assertTrue("Timeout waiting for FX runtime to start", startupLatch.await(15, TimeUnit.SECONDS));
90+
}
91+
92+
@Test
93+
public void testTimeForAdding500NodesToScene() throws Exception {
94+
95+
Util.runAndWait(() -> {
96+
// Compute time for adding 500 Nodes
97+
long startTime = System.currentTimeMillis();
98+
99+
HBox hbox = new HBox();
100+
for (int i = 0; i < 500; i++) {
101+
hbox = new HBox(new Text("y"), hbox);
102+
final HBox h = hbox;
103+
h.setPadding(new Insets(1));
104+
}
105+
rootPane.setCenter(hbox);
106+
107+
long endTime = System.currentTimeMillis();
108+
109+
System.out.println("Time to create and add 500 nodes to a Scene = " +
110+
(endTime - startTime) + " mSec");
111+
112+
// NOTE : 800 mSec is not a benchmark value
113+
// It is good enough to catch the regression in performance, if any
114+
assertTrue("Time to add 500 Nodes is more than 800 mSec", (endTime - startTime) < 800);
115+
});
116+
}
117+
118+
@AfterClass
119+
public static void teardownOnce() {
120+
Platform.runLater(() -> {
121+
stage.hide();
122+
Platform.exit();
123+
});
124+
}
125+
}

0 commit comments

Comments
 (0)