On Fri, 15 Nov 2019 09:14:04 GMT, Ajit Ghaisas <aghai...@openjdk.org> wrote:
> On Thu, 14 Nov 2019 18:33:05 GMT, Kevin Rushforth <k...@openjdk.org> wrote: > >> On Tue, 12 Nov 2019 16:45:04 GMT, Ajit Ghaisas <aghai...@openjdk.org> wrote: >> >>> **Issue :** >>> https://bugs.openjdk.java.net/browse/JDK-8193445 >>> >>> **Background :** >>> The CSS performance improvement done in >>> [JDK-8151756](https://bugs.openjdk.java.net/browse/JDK-8151756) had to be >>> backed out due to functional regressions reported in >>> [JDK-8185709](https://bugs.openjdk.java.net/browse/JDK-8185709), >>> [JDK-8183100](https://bugs.openjdk.java.net/browse/JDK-8183100) and >>> [JDK-8168951](https://bugs.openjdk.java.net/browse/JDK-8168951). >>> Refer to [JDK-8183100](https://bugs.openjdk.java.net/browse/JDK-8183100) >>> for more details on this backout. >>> >>> **Description :** >>> This PR reintroduces the CSS performance improvement fix done in >>> [JDK-8151756](https://bugs.openjdk.java.net/browse/JDK-8151756) while >>> addressing the functional regressions that were reported in >>> [JDK-8185709](https://bugs.openjdk.java.net/browse/JDK-8185709), >>> [JDK-8183100](https://bugs.openjdk.java.net/browse/JDK-8183100) and >>> [JDK-8168951](https://bugs.openjdk.java.net/browse/JDK-8168951). >>> For ease of review, I have made two separate commits - >>> 1) [Commit >>> 1](https://github.com/openjdk/jfx/pull/34/commits/d964675ebc2a42f2fd6928b773819502683f2334) >>> - Reintroduces the CSS performance improvement fix done in >>> [JDK-8151756](https://bugs.openjdk.java.net/browse/JDK-8151756) - most of >>> the patch applied cleanly. >>> 2) [Commit 2 >>> ](https://github.com/openjdk/jfx/pull/34/commits/12ea8220a730ff8d98d520ce870691d54f0de00f)- >>> fixes the functional regressions keeping performance improvement intact + >>> adds a system test >>> >>> **Root Cause :** >>> CSS performance improvement fix proposed in [JDK-8151756 >>> ](https://bugs.openjdk.java.net/browse/JDK-8151756)correctly avoids the >>> redundant CSS reapplication to children of a Parent. >>> What was missed earlier in [JDK-8151756 >>> ](https://bugs.openjdk.java.net/browse/JDK-8151756) fix : "CSS >>> reapplication to the Parent itself”. >>> This missing piece was the root cause of all functional regressions >>> reported against >>> [JDK-8151756](https://bugs.openjdk.java.net/browse/JDK-8151756) >>> >>> **Fix :** >>> Fixed the identified root cause. See commit 2. >>> >>> **Testing :** >>> 1. All passing unit tests continue to pass >>> 2. New system test (based on >>> [JDK-8209830](https://bugs.openjdk.java.net/browse/JDK-8209830)) added in >>> this PR - fails before this fix and passes after the fix >>> 3. System test JDK8183100Test continues to pass >>> 4. All test cases attached to regressions >>> [JDK-8185709](https://bugs.openjdk.java.net/browse/JDK-8185709), >>> [JDK-8183100](https://bugs.openjdk.java.net/browse/JDK-8183100) and >>> [JDK-8168951](https://bugs.openjdk.java.net/browse/JDK-8168951) pass with >>> this fix >>> >>> In addition, testing by community with specific CSS performance / >>> functionality will be helpful. >>> >>> ---------------- >>> >>> Commits: >>> - 12ea8220: Fix for functional regressions of JDK-8151756 + add a sytem >>> test >>> - d964675e: Reintroduce JDK-8151756 CSS performance fix >>> >>> Changes: https://git.openjdk.java.net/jfx/pull/34/files >>> Webrev: https://webrevs.openjdk.java.net/jfx/34/webrev.00 >>> Issue: https://bugs.openjdk.java.net/browse/JDK-8193445 >>> Stats: 121 lines in 5 files changed: 104 ins; 0 del; 17 mod >>> Patch: https://git.openjdk.java.net/jfx/pull/34.diff >>> Fetch: git fetch https://git.openjdk.java.net/jfx pull/34/head:pull/34 >> >> While we are still discussing the fix itself, I added a few comments on the >> new test. It generally looks good, but should be run on a variety of >> systems, with and without the fix (once we have a final fix that we are >> satisfied with). >> >> tests/system/src/test/java/test/robot/javafx/scene/CSSPerf_JDK8193445Test.java >> line 26: >> >>> 25: >>> 26: package test.robot.javafx.scene; >>> 27: >> >> There is no need for this test to require robot. I recommend moving it to >> `test.javafx.scene` (and not inherit from `VisualTestBase`). >> >> tests/system/src/test/java/test/robot/javafx/scene/CSSPerf_JDK8193445Test.java >> line 55: >> >>> 54: >>> 55: public class CSSPerf_JDK8193445Test extends VisualTestBase { >>> 56: >> >> We have moved away from putting the bug ID in the test class name, so I >> recommend renaming it. >> >> tests/system/src/test/java/test/robot/javafx/scene/CSSPerf_JDK8193445Test.java >> line 78: >> >>> 77: HBox hbox = new HBox(); >>> 78: for (int i = 0; i < 300; i++) { >>> 79: hbox = new HBox(new Text("y"), hbox); >> >> In my testing on various machines, the bug is more pronounced, and less >> prone to system differences with `500` nodes instead of `300`. >> >> tests/system/src/test/java/test/robot/javafx/scene/CSSPerf_JDK8193445Test.java >> line 94: >> >>> 93: // It is good enough to catch the regression in performance, if >>> any >>> 94: assertTrue("Time to add 300 Nodes is more than 400 mSec", mSec >>> < 400); >>> 95: } >> >> If you increase the number of nodes to `500` then I recommend bumping the >> time threshold to `800` msec in case it is run on a very slow system. > >> I think inverting the call is fine. That's what I did in my fix >> ([DeanWookey/openjdk-jfx@65a1ed8](https://github.com/DeanWookey/openjdk-jfx/commit/65a1ed82bce262294f1969e9a12e1126ec8a1ec6)) >> and we've been testing that out thoroughly for over a year. >> >> It's as if you are adding nodes 1 by 1 to the scene graph, something we know >> works and is fast. My change tries to emulate that more accurately to avoid >> side effects. Theoretically, we should be able to do better when many nodes >> are added at once because we have all the information upfront. >> >> The one side effect I can see by only applying commit 2 is that the first >> call of reapplyCSS() calls reapplyCss on every node in the tree and that >> sets the cssFlag = CssFlags.UPDATE;. The subsequent calls will hit this in >> reapplyCSS(): >> >> ``` >> if (cssFlag == CssFlags.UPDATE) { >> cssFlag = CssFlags.REAPPLY; >> notifyParentsOfInvalidatedCSS(); >> return; >> } >> ``` >> >> and return without doing all the unnecessary work. As a result however, >> instead of leaving with cssFlag = CssFlags.UPDATE, all the nodes leave with >> CssFlags.REAPPLY. That might cause an unnecessary css pass later? >> >> Doing it in the order it happens now, that check for the update flag >> shouldn't be true because its bottom up. > > It is a good observation about cssFlag. I have not seen any side effect with > the limited testing that I have done. It may be possible that the > "unnecessary css pass later" scenario is not covered by the test cases that > we have. > Perhaps short-circuiting the call to reapplyCss() from the reapplyCSS() > method is the thing to do. This comment from @dsgrieve got me interested. I checked the test code JDK-8151756 with cssFlags logged, it became evident that the cssFlag gets set to DIRTY_BRANCH for every parent and reapplyCss() gets invoked for each of the children. This is the exact redundant processing. Test from JDK-8151756 with additional one level of Node hierarchy. Parent1<--Parent2<--Parent3<--Rectangle (leaf child) Log from test program ---- Parent 1 : VBox@1d9e402b Parent 2 : VBox@4cc2dcce Parent 3 : VBox@4cc2dcce Rectangle **REAPPLY_CSS called for : VBox@1d9e402b ----- CssFlags.CLEAN REAPPLY_CSS called for : Rectangle[...] ----- CssFlags.CLEAN** reapplyCss called for : Rectangle[...] ----- CssFlags.CLEAN **REAPPLY_CSS called for : VBox@19234c0d ----- CssFlags.DIRTY_BRANCH** reapplyCss called for : VBox@19234c0d ----- CssFlags.DIRTY_BRANCH reapplyCss called for : Rectangle[...] ----- CssFlags.CLEAN **REAPPLY_CSS called for : VBox@4cc2dcce ----- CssFlags.DIRTY_BRANCH** reapplyCss called for : VBox@4cc2dcce ----- CssFlags.DIRTY_BRANCH reapplyCss called for : VBox@19234c0d ----- CssFlags.UPDATE reapplyCss called for : Rectangle[...] ----- CssFlags.CLEAN **REAPPLY_CSS called for : VBox@1d9e402b ----- CssFlags.DIRTY_BRANCH** reapplyCss called for : VBox@1d9e402b ----- CssFlags.DIRTY_BRANCH reapplyCss called for : VBox@4cc2dcce ----- CssFlags.UPDATE reapplyCss called for : VBox@19234c0d ----- CssFlags.UPDATE reapplyCss called for : Rectangle[...] ----- CssFlags.CLEAN Proposed New Fix : ------------------- I added a simple check to avoid reapplyCss() call for each Node with DIRTY_BRANCH cssFlag. Here is the patch - diff --git a/modules/javafx.graphics/src/main/java/javafx/scene/Node.java b/modules/javafx.graphics/src/main/java/javafx/scene/Node.java index 877e0fd6c8..8606dfb575 100644 --- a/modules/javafx.graphics/src/main/java/javafx/scene/Node.java +++ b/modules/javafx.graphics/src/main/java/javafx/scene/Node.java @@ -9416,7 +9416,7 @@ public abstract class Node implements EventTarget, Styleable { if (cssFlag == CssFlags.REAPPLY) return; // RT-36838 - don't reapply CSS in the middle of an update - if (cssFlag == CssFlags.UPDATE) { + if (cssFlag == CssFlags.UPDATE || cssFlag == CssFlags.DIRTY_BRANCH) { cssFlag = CssFlags.REAPPLY; notifyParentsOfInvalidatedCSS(); return; With this fix - Log from test program ---- Parent 1 : VBox@36d24c70 Parent 2 : VBox@35af5cea Parent 3 : VBox@35af5cea Rectangle **REAPPLY_CSS called for : VBox@36d24c70 ----- CssFlags.CLEAN** **REAPPLY_CSS called for : Rectangle[...] ----- CssFlags.CLEAN** reapplyCss called for : Rectangle[...] ----- CssFlags.CLEAN **REAPPLY_CSS called for : VBox@5d4b6983 ----- CssFlags.DIRTY_BRANCH REAPPLY_CSS called for : VBox@35af5cea ----- CssFlags.DIRTY_BRANCH REAPPLY_CSS called for : VBox@36d24c70 ----- CssFlags.DIRTY_BRANCH** reapplyCss called for : VBox@36d24c70 ----- CssFlags.REAPPLY reapplyCss called for : VBox@35af5cea ----- CssFlags.REAPPLY reapplyCss called for : VBox@5d4b6983 ----- CssFlags.REAPPLY reapplyCss called for : Rectangle[...] ----- CssFlags.CLEAN I verified that all graphics/controls unit tests & all system tests pass with this fix. I launched and played with Ensemble app. I did not see any visible artifacts. PR: https://git.openjdk.java.net/jfx/pull/34