tests: Vendor blink perf tests (#38654)

Vendors the [blink perf
tests](https://chromium.googlesource.com/chromium/src/+/HEAD/third_party/blink/perf_tests/).
These perf tests are useful to evaluate the performance of servo. 
The license that governs the perf tests is included in the folder. 
Running benchmark cases automatically is left to future work.

The update.py script is taken from mozjs and slightly adapted, so we can
easily filter
(and patch if this should be necessary in the future.

Testing: This PR just adds the perf_tests, but does not use or modify
them in any way.

---------

Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
This commit is contained in:
Jonathan Schwender 2025-08-17 11:54:04 +02:00 committed by GitHub
parent 7621332824
commit ee781b71b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
648 changed files with 359694 additions and 0 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,34 @@
// Perf Tests run a maximum of 20 times,
// make sure we have an equal amount of characters
// for each run.
var selectionSize = fallbackChars.length / 21;
var target;
function test() {
var charSelection = "";
for(var i=0; i < selectionSize; i++) {
var selectedCharIndex = Math.floor(Math.random() * fallbackChars.length);
if(!fallbackChars[selectedCharIndex])
continue;
charSelection += fallbackChars[selectedCharIndex];
fallbackChars.splice(selectedCharIndex, 1);
}
if (charSelection.length)
replaceTextAndWaitForLayout(charSelection);
}
function replaceTextAndWaitForLayout(charSelection) {
while (target.firstChild)
target.removeChild(target.firstChild);
target.appendChild(document.createTextNode(charSelection));
PerfTestRunner.forceLayout();
}
function cleanup() {
replaceTextAndWaitForLayout("");
}
function startTest() {
target = document.querySelector("#target");
PerfTestRunner.measureTime({ run: test, done: cleanup, description: "Per-character font fallback" });
}

View file

@ -0,0 +1,18 @@
.container {
display: none;
}
.float {
float: left;
width: 5px;
height: 5px;
border: 1px solid green;
}
.big {
width: 10px;
}
.float-end {
clear:left;
}

View file

@ -0,0 +1,61 @@
(function() {
function createElement(tag, parent, className, id) {
var el = document.createElement(tag);
el.className = className;
if (id)
el.id = id;
parent.appendChild(el);
return el;
}
function createSet(width, height, nested) {
var container = createElement("div", document.body, "container");
for (var y = 0; y < height; ++y) {
for (var x = 0; x < width; ++x)
createElement("div", container, "float", "float" + x + "_" + y);
var nestedContainer = container;
for ( ; nested > 0; --nested)
nestedContainer = createElement("div", nestedContainer, "nested", "nested" + x + "_" + nested);
createElement("div", container, "float-end", "end" + x)
}
return container;
}
function toggle(str, str1, str2) {
return str == str1 ? str2 : str1;
}
function resetTest() {
PerfTestRunner.resetRandomSeed();
var list = document.querySelectorAll(".float.big");
for (var i = 0; i < list.length; ++i)
list[i].className = "float";
}
function createTestFunction(width, height, nested, runs, rows) {
var containers = [];
for (var i = 0; i < rows; ++i)
containers[i] = createSet(width, height, nested);
nested = nested || 0;
runs = runs || 10;
return function() {
for (var c = 0; c < rows; ++c) {
container = containers[c];
container.style.display = "block";
for (var i = 0; i < runs; ++i) {
var x = Math.floor(Math.random() * width);
var y = Math.floor(Math.random() * height);
var el = document.getElementById("float" + x + "_" + y);
el.className = toggle(el.className, "float", "float big");
PerfTestRunner.forceLayout();
}
resetTest();
container.style.display = "none";
}
}
}
window.createFloatsLayoutTestFunction = createTestFunction;
})();

View file

@ -0,0 +1,14 @@
html, body {
margin: 0;
}
table {
border-collapse: collapse;
border : 1px solid red;
}
td {
border : 1px solid blue;
width: 5px;
height: 5px;
}

View file

@ -0,0 +1,32 @@
(function() {
function createElement(tag, parent, className, id) {
var el = document.createElement(tag);
el.className = className;
if (id)
el.id = id;
parent.appendChild(el);
return el;
}
function createTable(width, height, colspan) {
var table = createElement("table", document.body, "table");
for (var y = 0; y < height; ++y) {
var tr = createElement("tr", table, "tr");
for (var x = 0; x < width; ++x) {
var td = createElement("td", tr, "td");
if (colspan > 0 && x==10 && y==0)
table.rows[y].cells[x].colSpan = colspan;
}
}
return table;
}
function createTestFunction(width, height, colspan) {
return function() {
var table = createTable(width, height, colspan);
PerfTestRunner.forceLayout();
}
}
window.createTableTestFunction = createTestFunction;
})();

View file

@ -0,0 +1,110 @@
'use strict';
class LineLayoutPerfTest {
constructor(container) {
this.container = container;
this.spanCount = 0;
this.lineCount = 10000;
this.wordCountPerLine = 20;
this.uniqueWordCount = 100;
this.wordLength = 8;
this.wordSeparator = ' ';
}
run(description) {
// Unblock onload event by scheduling with zero delay,
// in order to avoid perf bot flakiness where the bot checks
// for timeouts reaching onload event, see crbug.com/457194
window.setTimeout(() => {
PerfTestRunner.measureTime({
description: description,
run: this.measure.bind(this)
});
}, 0);
}
measure() {
var fragment = this.createFragment();
PerfTestRunner.forceLayout();
var now = PerfTestRunner.now();
this.container.appendChild(fragment);
PerfTestRunner.forceLayout();
var resultTime = PerfTestRunner.now() - now;
while (this.container.firstChild)
this.container.removeChild(this.container.lastChild);
return resultTime;
}
createFragment() {
return TextGenerator.createFragment(this.spanCount, this.lineCount,
this.wordCountPerLine, this.wordSeparator,
this.createWordGenerator());
}
createWordGenerator() {
return TextGenerator.createWordPoolGenerator(this.uniqueWordCount, this.wordLength);
}
}
class LongWordPerfTest extends LineLayoutPerfTest {
constructor(container, wordLength) {
super(container);
this.lineCount = 1;
this.wordCountPerLine = 1;
this.wordLength = wordLength;
}
createWordGenerator() {
return () => TextGenerator.createWord(this.wordLength);
}
}
class TextGenerator {
static createFragment(spanCount, lineCount, wordCountPerLine, wordSeparator, nextWord) {
if (spanCount <= 0)
return document.createTextNode(TextGenerator.createLines(lineCount, wordCountPerLine, wordSeparator, nextWord));
var fragment = document.createDocumentFragment();
for (var elementIndex = 0; elementIndex < spanCount; elementIndex++) {
var child = document.createElement('span');
child.textContent = TextGenerator.createLines(lineCount, wordCountPerLine, wordSeparator, nextWord);
fragment.appendChild(child);
}
return fragment;
}
static createLines(lineCount, wordCountPerLine, wordSeparator, nextWord) {
var lines = [];
for (var lineIndex = 0; lineIndex < lineCount; lineIndex++)
lines.push(this.createLine(wordCountPerLine, wordSeparator, nextWord));
return lines.join('\n');
}
static createLine(wordCountPerLine, wordSeparator, nextWord) {
let words = [];
for (var wordIndex = 0; wordIndex < wordCountPerLine; wordIndex++)
words.push(nextWord());
return words.join(wordSeparator);
}
static createWordPoolGenerator(wordCount, wordLength) {
var words = [];
for (var i = 0; i < wordCount; i++)
words.push(TextGenerator.createWord(wordLength));
return () => {
return words[Math.floor(Math.random() * words.length)];
};
}
static createWord(length) {
var pieces = [];
while (length > 0) {
var piece = Math.random().toString(36).slice(2);
pieces.push(piece.slice(0, length));
length -= piece.length;
}
return pieces.join('');
}
}