summaryrefslogtreecommitdiffstats
path: root/dom/serviceworkers/test/performance
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /dom/serviceworkers/test/performance
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/serviceworkers/test/performance')
-rw-r--r--dom/serviceworkers/test/performance/intercepted.txt1
-rw-r--r--dom/serviceworkers/test/performance/perftest.toml14
-rw-r--r--dom/serviceworkers/test/performance/perfutils.js46
-rw-r--r--dom/serviceworkers/test/performance/sw_cacher.js18
-rw-r--r--dom/serviceworkers/test/performance/sw_empty.js0
-rw-r--r--dom/serviceworkers/test/performance/sw_intercept_target.js7
-rw-r--r--dom/serviceworkers/test/performance/target.txt1
-rw-r--r--dom/serviceworkers/test/performance/test_caching.html89
-rw-r--r--dom/serviceworkers/test/performance/test_fetch.html168
-rw-r--r--dom/serviceworkers/test/performance/test_registration.html89
-rw-r--r--dom/serviceworkers/test/performance/time_fetch.html38
11 files changed, 471 insertions, 0 deletions
diff --git a/dom/serviceworkers/test/performance/intercepted.txt b/dom/serviceworkers/test/performance/intercepted.txt
new file mode 100644
index 0000000000..87c7a8efe7
--- /dev/null
+++ b/dom/serviceworkers/test/performance/intercepted.txt
@@ -0,0 +1 @@
+intercepted
diff --git a/dom/serviceworkers/test/performance/perftest.toml b/dom/serviceworkers/test/performance/perftest.toml
new file mode 100644
index 0000000000..6a7e5928be
--- /dev/null
+++ b/dom/serviceworkers/test/performance/perftest.toml
@@ -0,0 +1,14 @@
+[DEFAULT]
+support-files = [
+ "intercepted.txt",
+ "perfutils.js",
+ "sw_cacher.js",
+ "sw_empty.js",
+ "sw_intercept_target.js",
+ "target.txt",
+ "time_fetch.html",
+]
+
+["test_caching.html"]
+["test_fetch.html"]
+["test_registration.html"]
diff --git a/dom/serviceworkers/test/performance/perfutils.js b/dom/serviceworkers/test/performance/perfutils.js
new file mode 100644
index 0000000000..d7edbe2fe7
--- /dev/null
+++ b/dom/serviceworkers/test/performance/perfutils.js
@@ -0,0 +1,46 @@
+"use strict";
+
+/**
+ * Given a map from test names to arrays of results, report perfherder metrics
+ * and log full results.
+ */
+function reportMetrics(journal) {
+ let metrics = {};
+ let text = "\nResults (ms)\n";
+
+ const names = Object.keys(journal);
+ const prefixLen = 1 + Math.max(...names.map(str => str.length));
+
+ for (const name in journal) {
+ const med = median(journal[name]);
+ text += (name + ":").padEnd(prefixLen, " ") + stringify(journal[name]);
+ text += " median " + med + "\n";
+ metrics[name] = med;
+ }
+
+ dump(text);
+ info("perfMetrics", JSON.stringify(metrics));
+}
+
+function median(arr) {
+ arr = [...arr].sort((a, b) => a - b);
+ const mid = Math.floor(arr.length / 2);
+
+ if (arr.length % 2) {
+ return arr[mid];
+ }
+
+ return (arr[mid - 1] + arr[mid]) / 2;
+}
+
+function stringify(arr) {
+ function pad(num) {
+ let s = num.toString().padStart(5, " ");
+ if (s[0] != " ") {
+ s = " " + s;
+ }
+ return s;
+ }
+
+ return arr.reduce((acc, elem) => acc + pad(elem), "");
+}
diff --git a/dom/serviceworkers/test/performance/sw_cacher.js b/dom/serviceworkers/test/performance/sw_cacher.js
new file mode 100644
index 0000000000..5a441ef785
--- /dev/null
+++ b/dom/serviceworkers/test/performance/sw_cacher.js
@@ -0,0 +1,18 @@
+"use strict";
+
+oninstall = function (event) {
+ event.waitUntil(
+ caches.open("perftest").then(function (cache) {
+ return cache.put("cached.txt", new Response("cached.txt"));
+ })
+ );
+};
+
+onfetch = function (event) {
+ if (event.request.url.endsWith("/cached.txt")) {
+ var p = caches.match("cached.txt", { cacheName: "perftest" });
+ event.respondWith(p);
+ } else if (event.request.url.endsWith("/uncached.txt")) {
+ event.respondWith(new Response("uncached.txt"));
+ }
+};
diff --git a/dom/serviceworkers/test/performance/sw_empty.js b/dom/serviceworkers/test/performance/sw_empty.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/dom/serviceworkers/test/performance/sw_empty.js
diff --git a/dom/serviceworkers/test/performance/sw_intercept_target.js b/dom/serviceworkers/test/performance/sw_intercept_target.js
new file mode 100644
index 0000000000..47b3853978
--- /dev/null
+++ b/dom/serviceworkers/test/performance/sw_intercept_target.js
@@ -0,0 +1,7 @@
+"use strict";
+
+onfetch = function (event) {
+ if (event.request.url.indexOf("target.txt") != -1) {
+ event.respondWith(fetch("intercepted.txt"));
+ }
+};
diff --git a/dom/serviceworkers/test/performance/target.txt b/dom/serviceworkers/test/performance/target.txt
new file mode 100644
index 0000000000..eb5a316cbd
--- /dev/null
+++ b/dom/serviceworkers/test/performance/target.txt
@@ -0,0 +1 @@
+target
diff --git a/dom/serviceworkers/test/performance/test_caching.html b/dom/serviceworkers/test/performance/test_caching.html
new file mode 100644
index 0000000000..cd6d4cf493
--- /dev/null
+++ b/dom/serviceworkers/test/performance/test_caching.html
@@ -0,0 +1,89 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Service worker performance test: caching</title>
+</head>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script src="../utils.js"></script>
+<script src="perfutils.js"></script>
+<script>
+
+ "use strict";
+
+ const NO_CACHE = "No cache";
+ const CACHED = "Cached";
+ const NO_CACHE_AGAIN = "No cache again";
+
+ var journal = {};
+ journal[NO_CACHE] = [];
+ journal[CACHED] = [];
+ journal[NO_CACHE_AGAIN] = [];
+
+ const ITERATIONS = 10;
+
+ var perfMetadata = {
+ owner: "DOM LWS",
+ name: "Service Worker Caching",
+ description: "Test service worker caching.",
+ options: {
+ default: {
+ perfherder: true,
+ perfherder_metrics: [
+ // Here, we can't use the constants defined above because perfherder
+ // grabs data from the parse tree.
+ { name: "No cache", unit: "ms", shouldAlert: true },
+ { name: "Cached", unit: "ms", shouldAlert: true },
+ { name: "No cache again", unit: "ms", shouldAlert: true },
+ ],
+ verbose: true,
+ manifest: "perftest.toml",
+ manifest_flavor: "plain",
+ },
+ },
+ };
+
+ add_task(async () => {
+ await SpecialPowers.pushPrefEnv({
+ set: [["dom.serviceWorkers.testing.enabled", true]]
+ });
+ });
+
+ function create_iframe(url) {
+ return new Promise(function(res) {
+ let iframe = document.createElement("iframe");
+ iframe.src = url;
+ iframe.onload = function() { res(iframe) }
+ document.body.appendChild(iframe);
+ });
+ }
+
+ async function time_fetch(journal, iframe, filename) {
+ for (let i = 0; i < ITERATIONS; i++) {
+ let result = await iframe.contentWindow.time_fetch(filename);
+ is(result.status, 200);
+ is(result.data, filename);
+ journal.push(result.elapsed_ms);
+ }
+ }
+
+ add_task(async () => {
+ let reg = await navigator.serviceWorker.register("sw_cacher.js");
+ await waitForState(reg.installing, "activated");
+
+ let iframe = await create_iframe("time_fetch.html");
+
+ await time_fetch(journal[NO_CACHE], iframe, "uncached.txt");
+ await time_fetch(journal[CACHED], iframe, "cached.txt");
+ await time_fetch(journal[NO_CACHE_AGAIN], iframe, "uncached.txt");
+
+ await reg.unregister();
+ });
+
+ add_task(() => {
+ reportMetrics(journal);
+ });
+
+</script>
+<body>
+</body>
+</html>
diff --git a/dom/serviceworkers/test/performance/test_fetch.html b/dom/serviceworkers/test/performance/test_fetch.html
new file mode 100644
index 0000000000..29dd65b595
--- /dev/null
+++ b/dom/serviceworkers/test/performance/test_fetch.html
@@ -0,0 +1,168 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Service worker performance test: fetch</title>
+</head>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script src="../utils.js"></script>
+<script src="perfutils.js"></script>
+<script>
+
+ "use strict";
+
+ const COLD_FETCH = "Cold fetch";
+ const UNDISTURBED_FETCH = "Undisturbed fetch";
+ const INTERCEPTED_FETCH = "Intercepted fetch";
+ const LIBERATED_FETCH = "Liberated fetch";
+ const UNDISTURBED_XHR = "Undisturbed XHR";
+ const INTERCEPTED_XHR = "Intercepted XHR";
+ const LIBERATED_XHR = "Liberated XHR";
+
+ var journal = {};
+ journal[COLD_FETCH] = [];
+ journal[UNDISTURBED_FETCH] = [];
+ journal[INTERCEPTED_FETCH] = [];
+ journal[LIBERATED_FETCH] = [];
+ journal[UNDISTURBED_XHR] = [];
+ journal[INTERCEPTED_XHR] = [];
+ journal[LIBERATED_XHR] = [];
+
+ const ITERATIONS = 10;
+
+ var perfMetadata = {
+ owner: "DOM LWS",
+ name: "Service Worker Fetch",
+ description: "Test cold and warm fetches.",
+ options: {
+ default: {
+ perfherder: true,
+ perfherder_metrics: [
+ // Here, we can't use the constants defined above because perfherder
+ // grabs data from the parse tree.
+ { name: "Cold fetch", unit: "ms", shouldAlert: true },
+ { name: "Undisturbed fetch", unit: "ms", shouldAlert: true },
+ { name: "Intercepted fetch", unit: "ms", shouldAlert: true },
+ { name: "Liberated fetch", unit: "ms", shouldAlert: true },
+ { name: "Undisturbed XHR", unit: "ms", shouldAlert: true },
+ { name: "Intercepted XHR", unit: "ms", shouldAlert: true },
+ { name: "Liberated XHR", unit: "ms", shouldAlert: true },
+ ],
+ verbose: true,
+ manifest: "perftest.toml",
+ manifest_flavor: "plain",
+ },
+ },
+ };
+
+ function create_iframe(url) {
+ return new Promise(function(res) {
+ let iframe = document.createElement("iframe");
+ iframe.src = url;
+ iframe.onload = function() { res(iframe) }
+ document.body.appendChild(iframe);
+ });
+ }
+
+ add_task(async () => {
+ await SpecialPowers.pushPrefEnv({
+ set: [["dom.serviceWorkers.testing.enabled", true]]
+ });
+ });
+
+ /**
+ * Time fetch from a fresh service worker.
+ */
+ add_task(async () => {
+ for (let i = 0; i < ITERATIONS; i++) {
+ let reg = await navigator.serviceWorker.register("sw_intercept_target.js");
+ await waitForState(reg.installing, "activated");
+
+ let iframe = await create_iframe("time_fetch.html");
+
+ let result = await iframe.contentWindow.time_fetch("target.txt");
+ is(result.status, 200);
+ is(result.data, "intercepted\n");
+ journal[COLD_FETCH].push(result.elapsed_ms);
+
+ ok(document.body.removeChild(iframe), "Failed to remove child iframe");
+
+ await reg.unregister();
+ }
+ });
+
+ /**
+ * Time unintercepted fetch, intercepted fetch, then unintercepted
+ * fetch again.
+ */
+ add_task(async () => {
+ let reg = await navigator.serviceWorker.register("sw_intercept_target.js");
+ await waitForState(reg.installing, "activated");
+
+ async function measure(journal, sw_enabled) {
+ await SpecialPowers.pushPrefEnv({
+ set: [["dom.serviceWorkers.enabled", sw_enabled]]
+ });
+
+ let iframe = await create_iframe("time_fetch.html");
+
+ for (let i = 0; i < ITERATIONS; i++) {
+ let result = await iframe.contentWindow.time_fetch("target.txt");
+ is(result.status, 200);
+ is(result.data, sw_enabled ? "intercepted\n" : "target\n");
+ journal.push(result.elapsed_ms);
+ }
+
+ ok(document.body.removeChild(iframe), "Failed to remove child iframe");
+
+ await SpecialPowers.popPrefEnv();
+ }
+
+ await measure(journal[UNDISTURBED_FETCH], false);
+ await measure(journal[INTERCEPTED_FETCH], true);
+ await measure(journal[LIBERATED_FETCH], false);
+
+ await reg.unregister();
+ });
+
+ /**
+ * Time unintercepted XHR, intercepted XHR, then unintercepted
+ * XHR again.
+ */
+ add_task(async () => {
+ let reg = await navigator.serviceWorker.register("sw_intercept_target.js");
+ await waitForState(reg.installing, "activated");
+
+ async function measure(journal, sw_enabled) {
+ await SpecialPowers.pushPrefEnv({
+ set: [["dom.serviceWorkers.enabled", sw_enabled]]
+ });
+
+ let iframe = await create_iframe("time_fetch.html");
+
+ for (let i = 0; i < ITERATIONS; i++) {
+ let result = await iframe.contentWindow.time_xhr("target.txt");
+ is(result.status, 200);
+ is(result.data, sw_enabled ? "intercepted\n" : "target\n");
+ journal.push(result.elapsed_ms);
+ }
+
+ ok(document.body.removeChild(iframe), "Failed to remove child iframe");
+
+ await SpecialPowers.popPrefEnv();
+ }
+
+ await measure(journal[UNDISTURBED_XHR], false);
+ await measure(journal[INTERCEPTED_XHR], true);
+ await measure(journal[LIBERATED_XHR], false);
+
+ await reg.unregister();
+ });
+
+ add_task(() => {
+ reportMetrics(journal);
+ });
+
+</script>
+<body>
+</body>
+</html>
diff --git a/dom/serviceworkers/test/performance/test_registration.html b/dom/serviceworkers/test/performance/test_registration.html
new file mode 100644
index 0000000000..d5abbf6775
--- /dev/null
+++ b/dom/serviceworkers/test/performance/test_registration.html
@@ -0,0 +1,89 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Service worker performance test: registration</title>
+</head>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script src="../utils.js"></script>
+<script src="perfutils.js"></script>
+<script>
+
+ "use strict";
+
+ const REGISTRATION = "Registration";
+ const ACTIVATION = "Activation";
+ const UNREGISTRATION = "Unregistration";
+
+ var journal = [];
+ journal[REGISTRATION] = [];
+ journal[ACTIVATION] = [];
+ journal[UNREGISTRATION] = [];
+
+ const ITERATIONS = 10;
+
+ var perfMetadata = {
+ owner: "DOM LWS",
+ name: "Service Worker Registration",
+ description: "Test registration, activation, and unregistration.",
+ options: {
+ default: {
+ perfherder: true,
+ perfherder_metrics: [
+ // Here, we can't use the constants defined above because perfherder
+ // grabs data from the parse tree.
+ { name: "Registration", unit: "ms", shouldAlert: true },
+ { name: "Activation", unit: "ms", shouldAlert: true },
+ { name: "Unregistration", unit: "ms", shouldAlert: true },
+ ],
+ verbose: true,
+ manifest: "perftest.toml",
+ manifest_flavor: "plain",
+ },
+ },
+ };
+
+ function create_iframe(url) {
+ return new Promise(function(res) {
+ let iframe = document.createElement("iframe");
+ iframe.src = url;
+ iframe.onload = function() { res(iframe) }
+ document.body.appendChild(iframe);
+ });
+ }
+
+ add_task(async () => {
+ await SpecialPowers.pushPrefEnv({
+ set: [["dom.serviceWorkers.testing.enabled", true]]
+ });
+
+ async function measure() {
+ let begin_ts = performance.now();
+ let reg = await navigator.serviceWorker.register("sw_empty.js");
+ let reg_ts = performance.now();
+ await waitForState(reg.installing, "activated");
+ let act_ts = performance.now();
+ await reg.unregister();
+ let unreg_ts = performance.now();
+
+ journal[REGISTRATION].push(reg_ts - begin_ts);
+ journal[ACTIVATION].push(act_ts - reg_ts);
+ journal[UNREGISTRATION].push(unreg_ts - act_ts);
+ }
+
+ for (let i = 0; i < ITERATIONS; i++) {
+ await measure();
+ }
+
+ await SpecialPowers.popPrefEnv();
+
+ ok(true);
+ });
+
+ add_task(() => {
+ reportMetrics(journal);
+ });
+
+</script>
+<body>
+</body>
+</html>
diff --git a/dom/serviceworkers/test/performance/time_fetch.html b/dom/serviceworkers/test/performance/time_fetch.html
new file mode 100644
index 0000000000..a771d4889f
--- /dev/null
+++ b/dom/serviceworkers/test/performance/time_fetch.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script>
+
+ "use strict";
+
+ async function time_fetch(url) {
+ let start = performance.now();
+ let res = await fetch(url);
+ let elapsed = performance.now() - start;
+
+ return {
+ elapsed_ms : elapsed,
+ status : res.status,
+ data : await res.text()
+ };
+ }
+
+ async function time_xhr(url) {
+ let xhr = new XMLHttpRequest();
+ xhr.open("GET", url, false);
+ let start = performance.now();
+ xhr.send();
+ let elapsed = performance.now() - start;
+
+ return {
+ elapsed_ms : elapsed,
+ status : xhr.status,
+ data : xhr.responseText
+ }
+ }
+
+</script>
+</head>
+<body>
+</body>
+</html>