<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[225752] trunk/PerformanceTests</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/225752">225752</a></dd>
<dt>Author</dt> <dd>antti@apple.com</dd>
<dt>Date</dt> <dd>2017-12-11 11:41:46 -0800 (Mon, 11 Dec 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>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):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkPerformanceTestsChangeLog">trunk/PerformanceTests/ChangeLog</a></li>
<li><a href="#trunkPerformanceTestsStyleBenchindexhtml">trunk/PerformanceTests/StyleBench/index.html</a></li>
<li><a href="#trunkPerformanceTestsStyleBenchresourcesstylebenchjs">trunk/PerformanceTests/StyleBench/resources/style-bench.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkPerformanceTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/PerformanceTests/ChangeLog (225751 => 225752)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/PerformanceTests/ChangeLog 2017-12-11 19:22:01 UTC (rev 225751)
+++ trunk/PerformanceTests/ChangeLog    2017-12-11 19:41:46 UTC (rev 225752)
</span><span class="lines">@@ -1,3 +1,28 @@
</span><ins>+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):
+
</ins><span class="cx"> 2017-12-08  Konstantin Tokarev  <annulen@yandex.ru>
</span><span class="cx"> 
</span><span class="cx">         [python] Replace print operator with print() function for python3 compatibility
</span></span></pre></div>
<a id="trunkPerformanceTestsStyleBenchindexhtml"></a>
<div class="modfile"><h4>Modified: trunk/PerformanceTests/StyleBench/index.html (225751 => 225752)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/PerformanceTests/StyleBench/index.html     2017-12-11 19:22:01 UTC (rev 225751)
+++ trunk/PerformanceTests/StyleBench/index.html        2017-12-11 19:41:46 UTC (rev 225752)
</span><span class="lines">@@ -2,7 +2,7 @@
</span><span class="cx"> <html>
</span><span class="cx"> <head>
</span><span class="cx">     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</span><del>-    <title>StyleBench 0.1</title>
</del><ins>+    <title>StyleBench 0.2</title>
</ins><span class="cx">     <link rel="stylesheet" href="../Speedometer/resources/main.css">
</span><span class="cx">     <script src="../Speedometer/resources/main.js" defer></script>
</span><span class="cx">     <script src="../Speedometer/resources/benchmark-runner.js" defer></script>
</span></span></pre></div>
<a id="trunkPerformanceTestsStyleBenchresourcesstylebenchjs"></a>
<div class="modfile"><h4>Modified: trunk/PerformanceTests/StyleBench/resources/style-bench.js (225751 => 225752)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/PerformanceTests/StyleBench/resources/style-bench.js       2017-12-11 19:22:01 UTC (rev 225751)
+++ trunk/PerformanceTests/StyleBench/resources/style-bench.js  2017-12-11 19:41:46 UTC (rev 225752)
</span><span class="lines">@@ -12,9 +12,14 @@
</span><span class="cx">         return this.seed = this.seed * 16807 % 2147483647;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    underOne()
+    {
+        return (this.next % 1048576) / 1048576;
+    }
+
</ins><span class="cx">     chance(chance)
</span><span class="cx">     {
</span><del>-        return this.next % 1048576 < chance * 1048576;
</del><ins>+        return this.underOne() < chance;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     number(under)
</span><span class="lines">@@ -21,6 +26,13 @@
</span><span class="cx">     {
</span><span class="cx">         return this.next % under;
</span><span class="cx">     }
</span><ins>+
+    numberSquareWeightedToLow(under)
+    {
+        const random = this.underOne();
+        const random2 = random * random;
+        return Math.floor(random2 * under);
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> function nextAnimationFrame()
</span><span class="lines">@@ -35,6 +47,7 @@
</span><span class="cx">         return {
</span><span class="cx">             name: 'Default',
</span><span class="cx">             elementTypeCount: 10,
</span><ins>+            idChance: 0.05,
</ins><span class="cx">             elementChance: 0.5,
</span><span class="cx">             classCount: 200,
</span><span class="cx">             classChance: 0.3,
</span><span class="lines">@@ -85,6 +98,7 @@
</span><span class="cx">                 'first-of-type',
</span><span class="cx">                 'last-of-type',
</span><span class="cx">                 'only-of-type',
</span><ins>+                'empty',
</ins><span class="cx">             ],
</span><span class="cx">         });
</span><span class="cx">     }
</span><span class="lines">@@ -110,6 +124,7 @@
</span><span class="cx">     constructor(configuration)
</span><span class="cx">     {
</span><span class="cx">         this.configuration = configuration;
</span><ins>+        this.idCount = 0;
</ins><span class="cx"> 
</span><span class="cx">         this.baseStyle = document.createElement("style");
</span><span class="cx">         this.baseStyle.textContent = `
</span><span class="lines">@@ -119,10 +134,8 @@
</span><span class="cx">             }
</span><span class="cx">             #testroot * {
</span><span class="cx">                 display: inline-block;
</span><del>-            }
-            #testroot :empty {
-                width:10px;
</del><span class="cx">                 height:10px;
</span><ins>+                min-width:10px;
</ins><span class="cx">             }
</span><span class="cx">         `;
</span><span class="cx">         document.head.appendChild(this.baseStyle);
</span><span class="lines">@@ -137,19 +150,19 @@
</span><span class="cx">     randomElementName()
</span><span class="cx">     {
</span><span class="cx">         const elementTypeCount = this.configuration.elementTypeCount;
</span><del>-        return `elem${ this.random.number(elementTypeCount) }`;
</del><ins>+        return `elem${ this.random.numberSquareWeightedToLow(elementTypeCount) }`;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     randomClassName()
</span><span class="cx">     {
</span><span class="cx">         const classCount = this.configuration.classCount;
</span><del>-        return `class${ this.random.number(classCount) }`;
</del><ins>+        return `class${ this.random.numberSquareWeightedToLow(classCount) }`;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     randomClassNameFromRange(range)
</span><span class="cx">     {
</span><span class="cx">         const maximum = Math.round(range * this.configuration.classCount);
</span><del>-        return `class${ this.random.number(maximum) }`;
</del><ins>+        return `class${ this.random.numberSquareWeightedToLow(maximum) }`;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     randomCombinator()
</span><span class="lines">@@ -158,28 +171,44 @@
</span><span class="cx">         return combinators[this.random.number(combinators.length)]
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    randomPseudoClass()
</del><ins>+    randomPseudoClass(isLast)
</ins><span class="cx">     {
</span><span class="cx">         const pseudoClasses = this.configuration.pseudoClasses;
</span><del>-        return pseudoClasses[this.random.number(pseudoClasses.length)]
</del><ins>+        const pseudoClass = pseudoClasses[this.random.number(pseudoClasses.length)]
+        if (!isLast && pseudoClass == 'empty')
+            return this.randomPseudoClass(isLast);
+        return pseudoClass;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    makeSimpleSelector(index, length)
</del><ins>+    randomId()
</ins><span class="cx">     {
</span><ins>+        const idCount = this.configuration.idChance * this.configuration.elementCount ;
+        return `id${ this.random.number(idCount) }`;
+    }
+
+    makeCompoundSelector(index, length)
+    {
+        const isFirst = index == 0;
</ins><span class="cx">         const isLast = index == length - 1;
</span><span class="cx">         const usePseudoClass = this.random.chance(this.configuration.pseudoClassChance) && this.configuration.pseudoClasses.length;
</span><del>-        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);
</del><ins>+        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));
</ins><span class="cx">         const useBeforeOrAfter = isLast && this.random.chance(this.configuration.beforeAfterChance);
</span><span class="cx">         let result = "";
</span><span class="cx">         if (useElement)
</span><span class="cx">             result += this.randomElementName();
</span><ins>+        if (useId)
+            result += "#" + this.randomId();
</ins><span class="cx">         if (useClass) {
</span><del>-            // Use a smaller pool of class names on the left side of the selectors to create containers.
-            result += "." + this.randomClassNameFromRange((index + 1) / length);
</del><ins>+            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);
+            }
</ins><span class="cx">         }
</span><span class="cx">         if (usePseudoClass)
</span><del>-            result +=  ":" + this.randomPseudoClass();
</del><ins>+            result +=  ":" + this.randomPseudoClass(isLast);
</ins><span class="cx">         if (useBeforeOrAfter) {
</span><span class="cx">             if (this.random.chance(0.5))
</span><span class="cx">                 result +=  "::before";
</span><span class="lines">@@ -192,12 +221,12 @@
</span><span class="cx">     makeSelector()
</span><span class="cx">     {
</span><span class="cx">         const length = this.random.number(this.configuration.maximumSelectorLength) + 1;
</span><del>-        let result = this.makeSimpleSelector(0, length);
-        for (let i = 0; i < length; ++i) {
</del><ins>+        let result = this.makeCompoundSelector(0, length);
+        for (let i = 1; i < length; ++i) {
</ins><span class="cx">             const combinator = this.randomCombinator();
</span><span class="cx">             if (combinator != ' ')
</span><span class="cx">                 result += " " + combinator;
</span><del>-            result += " " + this.makeSimpleSelector(i, length);
</del><ins>+            result += " " + this.makeCompoundSelector(i, length);
</ins><span class="cx">         }
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="lines">@@ -212,7 +241,7 @@
</span><span class="cx">         let declaration = `background-color: rgb(${this.randomColorComponent}, ${this.randomColorComponent}, ${this.randomColorComponent});`;
</span><span class="cx"> 
</span><span class="cx">         if (selector.endsWith('::before') || selector.endsWith('::after'))
</span><del>-            declaration += " content: '\xa0';";
</del><ins>+            declaration += " content: ''; min-width:5px; display:inline-block;";
</ins><span class="cx"> 
</span><span class="cx">         return declaration;
</span><span class="cx">     }
</span><span class="lines">@@ -244,10 +273,15 @@
</span><span class="cx">         const element = document.createElement(this.randomElementName());
</span><span class="cx">         const hasClasses = this.random.chance(0.5);
</span><span class="cx">         if (hasClasses) {
</span><del>-            const count = this.random.number(3) + 1;
</del><ins>+            const count = this.random.numberSquareWeightedToLow(3) + 1;
</ins><span class="cx">             for (let i = 0; i < count; ++i)
</span><span class="cx">                 element.classList.add(this.randomClassName());
</span><span class="cx">         }
</span><ins>+        const hasId = this.random.chance(this.configuration.idChance);
+        if (hasId) {
+            element.id = `id${ this.idCount }`;
+            this.idCount++;
+        }
</ins><span class="cx">         return element;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>