StyleBench improvements
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 11 Dec 2017 19:41:46 +0000 (19:41 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 11 Dec 2017 19:41:46 +0000 (19:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=180646

Reviewed by Geoffrey Garen.

- Remove :empty rule from global stylesheet. It caused all tests to hit positional pseudo-class code paths.
- Instead use min-width to create easy flexible layout. Use it for ::before/::after too.
- Add :empty to positional pseudo-class test.
- Include some id attributes and id selectors
- Chance to have more than 1 classes per compound selector
- Change distribution of elements and classes to be non-uniform
- Other bug fixes

* StyleBench/resources/style-bench.js:
(Random.prototype.numberSquareWeightedToLow):
(Random):
(defaultConfiguration):
(prototype.randomElementName):
(prototype.randomId):
(prototype.makeCompoundSelector):
(prototype.makeSelector):
(prototype.makeElement):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@225752 268f45cc-cd09-0410-ab3c-d52691b4dbfc

PerformanceTests/ChangeLog
PerformanceTests/StyleBench/index.html
PerformanceTests/StyleBench/resources/style-bench.js

index 2a19511..beb2b3b 100644 (file)
@@ -1,3 +1,28 @@
+2017-12-11  Antti Koivisto  <antti@apple.com>
+
+        StyleBench improvements
+        https://bugs.webkit.org/show_bug.cgi?id=180646
+
+        Reviewed by Geoffrey Garen.
+
+        - Remove :empty rule from global stylesheet. It caused all tests to hit positional pseudo-class code paths.
+        - Instead use min-width to create easy flexible layout. Use it for ::before/::after too.
+        - Add :empty to positional pseudo-class test.
+        - Include some id attributes and id selectors
+        - Chance to have more than 1 classes per compound selector
+        - Change distribution of elements and classes to be non-uniform
+        - Other bug fixes
+
+        * StyleBench/resources/style-bench.js:
+        (Random.prototype.numberSquareWeightedToLow):
+        (Random):
+        (defaultConfiguration):
+        (prototype.randomElementName):
+        (prototype.randomId):
+        (prototype.makeCompoundSelector):
+        (prototype.makeSelector):
+        (prototype.makeElement):
+
 2017-12-08  Konstantin Tokarev  <annulen@yandex.ru>
 
         [python] Replace print operator with print() function for python3 compatibility
index 46af83b..06396bd 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>StyleBench 0.1</title>
+    <title>StyleBench 0.2</title>
     <link rel="stylesheet" href="../Speedometer/resources/main.css">
     <script src="../Speedometer/resources/main.js" defer></script>
     <script src="../Speedometer/resources/benchmark-runner.js" defer></script>
index 3765ba6..543650a 100644 (file)
@@ -12,15 +12,27 @@ class Random
         return this.seed = this.seed * 16807 % 2147483647;
     }
 
+    underOne()
+    {
+        return (this.next % 1048576) / 1048576;
+    }
+
     chance(chance)
     {
-        return this.next % 1048576 < chance * 1048576;
+        return this.underOne() < chance;
     }
 
     number(under)
     {
         return this.next % under;
     }
+
+    numberSquareWeightedToLow(under)
+    {
+        const random = this.underOne();
+        const random2 = random * random;
+        return Math.floor(random2 * under);
+    }
 }
 
 function nextAnimationFrame()
@@ -35,6 +47,7 @@ class StyleBench
         return {
             name: 'Default',
             elementTypeCount: 10,
+            idChance: 0.05,
             elementChance: 0.5,
             classCount: 200,
             classChance: 0.3,
@@ -85,6 +98,7 @@ class StyleBench
                 'first-of-type',
                 'last-of-type',
                 'only-of-type',
+                'empty',
             ],
         });
     }
@@ -110,6 +124,7 @@ class StyleBench
     constructor(configuration)
     {
         this.configuration = configuration;
+        this.idCount = 0;
 
         this.baseStyle = document.createElement("style");
         this.baseStyle.textContent = `
@@ -119,10 +134,8 @@ class StyleBench
             }
             #testroot * {
                 display: inline-block;
-            }
-            #testroot :empty {
-                width:10px;
                 height:10px;
+                min-width:10px;
             }
         `;
         document.head.appendChild(this.baseStyle);
@@ -137,19 +150,19 @@ class StyleBench
     randomElementName()
     {
         const elementTypeCount = this.configuration.elementTypeCount;
-        return `elem${ this.random.number(elementTypeCount) }`;
+        return `elem${ this.random.numberSquareWeightedToLow(elementTypeCount) }`;
     }
 
     randomClassName()
     {
         const classCount = this.configuration.classCount;
-        return `class${ this.random.number(classCount) }`;
+        return `class${ this.random.numberSquareWeightedToLow(classCount) }`;
     }
 
     randomClassNameFromRange(range)
     {
         const maximum = Math.round(range * this.configuration.classCount);
-        return `class${ this.random.number(maximum) }`;
+        return `class${ this.random.numberSquareWeightedToLow(maximum) }`;
     }
 
     randomCombinator()
@@ -158,28 +171,44 @@ class StyleBench
         return combinators[this.random.number(combinators.length)]
     }
 
-    randomPseudoClass()
+    randomPseudoClass(isLast)
     {
         const pseudoClasses = this.configuration.pseudoClasses;
-        return pseudoClasses[this.random.number(pseudoClasses.length)]
+        const pseudoClass = pseudoClasses[this.random.number(pseudoClasses.length)]
+        if (!isLast && pseudoClass == 'empty')
+            return this.randomPseudoClass(isLast);
+        return pseudoClass;
+    }
+
+    randomId()
+    {
+        const idCount = this.configuration.idChance * this.configuration.elementCount ;
+        return `id${ this.random.number(idCount) }`;
     }
 
-    makeSimpleSelector(index, length)
+    makeCompoundSelector(index, length)
     {
+        const isFirst = index == 0;
         const isLast = index == length - 1;
         const usePseudoClass = this.random.chance(this.configuration.pseudoClassChance) && this.configuration.pseudoClasses.length;
-        const useElement = usePseudoClass || this.random.chance(this.configuration.elementChance); // :nth-of-type etc only make sense with element
-        const useClass = !useElement || this.random.chance(this.configuration.classChance);
+        const useId = isFirst && this.random.chance(this.configuration.idChance);
+        const useElement = !useId && (usePseudoClass || this.random.chance(this.configuration.elementChance)); // :nth-of-type etc only make sense with element
+        const useClass = !useId && (!useElement || this.random.chance(this.configuration.classChance));
         const useBeforeOrAfter = isLast && this.random.chance(this.configuration.beforeAfterChance);
         let result = "";
         if (useElement)
             result += this.randomElementName();
+        if (useId)
+            result += "#" + this.randomId();
         if (useClass) {
-            // Use a smaller pool of class names on the left side of the selectors to create containers.
-            result += "." + this.randomClassNameFromRange((index + 1) / length);
+            const classCount = this.random.numberSquareWeightedToLow(2) + 1;
+            for (let i = 0; i < classCount; ++i) {
+                // Use a smaller pool of class names on the left side of the selectors to create containers.
+                result += "." + this.randomClassNameFromRange((index + 1) / length);
+            }
         }
         if (usePseudoClass)
-            result +=  ":" + this.randomPseudoClass();
+            result +=  ":" + this.randomPseudoClass(isLast);
         if (useBeforeOrAfter) {
             if (this.random.chance(0.5))
                 result +=  "::before";
@@ -192,12 +221,12 @@ class StyleBench
     makeSelector()
     {
         const length = this.random.number(this.configuration.maximumSelectorLength) + 1;
-        let result = this.makeSimpleSelector(0, length);
-        for (let i = 0; i < length; ++i) {
+        let result = this.makeCompoundSelector(0, length);
+        for (let i = 1; i < length; ++i) {
             const combinator = this.randomCombinator();
             if (combinator != ' ')
                 result += " " + combinator;
-            result += " " + this.makeSimpleSelector(i, length);
+            result += " " + this.makeCompoundSelector(i, length);
         }
         return result;
     }
@@ -212,7 +241,7 @@ class StyleBench
         let declaration = `background-color: rgb(${this.randomColorComponent}, ${this.randomColorComponent}, ${this.randomColorComponent});`;
 
         if (selector.endsWith('::before') || selector.endsWith('::after'))
-            declaration += " content: '\xa0';";
+            declaration += " content: ''; min-width:5px; display:inline-block;";
 
         return declaration;
     }
@@ -244,10 +273,15 @@ class StyleBench
         const element = document.createElement(this.randomElementName());
         const hasClasses = this.random.chance(0.5);
         if (hasClasses) {
-            const count = this.random.number(3) + 1;
+            const count = this.random.numberSquareWeightedToLow(3) + 1;
             for (let i = 0; i < count; ++i)
                 element.classList.add(this.randomClassName());
         }
+        const hasId = this.random.chance(this.configuration.idChance);
+        if (hasId) {
+            element.id = `id${ this.idCount }`;
+            this.idCount++;
+        }
         return element;
     }