Bug 1838925 - Browsertime tests for IndexedDB. r=perftest-reviewers,sparky,janv,canaltinova,dom-storage-reviewers,taskgraph-reviewers,ahal

Differential Revision: https://phabricator.services.mozilla.com/D181330
This commit is contained in:
Jari Jalkanen 2023-12-04 14:23:38 +00:00
Родитель 13ce96c39f
Коммит 3ba42c945c
13 изменённых файлов: 3721 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,8 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
---
name: IndexedDB
manifest: None
static-only: True
suites: {}

Просмотреть файл

@ -0,0 +1,66 @@
=============================
IndexedDB Performance Testing
=============================
How to run tests on CI:
-----------------------
* Windows: ``mach try perf --show-all -q "test-windows10-64-shippable-qr/opt-browsertime-indexeddb"``
* Linux: ``mach try perf --show-all -q "test-linux1804-64-shippable-qr/opt-browsertime-indexeddb"``
* Mac: ``mach try perf --show-all -q "test-macosx1015-64-shippable-qr/opt-browsertime-indexeddb"``
* All but 32-bit jobs: ``mach try perf --chrome --safari --show-all -q 'shippable-browsertime-indexeddb !32'``
* In general:
* Open test selection interface with ``mach try perf --show-all``
* Filter out the preferred tests by typing letters which are expected to be part of the test job name string (as in the -q argument above)
* Note down the string used as a filter for rerunning the job (or rerun it with ``mach try again --list-tasks`` and ``mach try again --index``)
How to run tests locally with the profiler?
-------------------------------------------
* Build the browser with release or release with debug symbols flags (not in debug mode)
* Use ``mach raptor --browsertime -t $(test_name) --gecko-profile --post-startup-delay=1000`` where test name, such as ``addMarN`` is one of the items listed in ``testing/raptor/raptor/tests/custom/browsertime-indexeddb.ini``
* After the test is complete, the generated profile is opened with the default browser.
* The generated profile file path is listed also in the command line output.
* For best symbolication results, it may help to
* run the same browser build that was used for the tests with ``./mach run``
* navigate to "profiler.firefox.com"
* use the "Load a profile from file" button
How to compare performance to a different browser?
--------------------------------------------------
* The test outputs a ``time_duration`` value for all supported browsers
* Using Chrome as an example,
* ``mach raptor --browsertime -t $(test_name) --post-startup-delay=1000 --app=chrome -b "/c/Program Files/Google/Chrome/Application/chrome.exe"``
* where test name, such as ``addMarN`` is one of the items listed in ``testing/raptor/raptor/tests/custom/browsertime-indexeddb.ini``
* browser executable path after the ``-b`` argument varies locally
* in some cases, a test driver argument such as ``--browsertime-chromedriver`` may be required
How to add more tests?
----------------------
* For the test boilerplate, copy and rename an old test script such as ``testing/raptor/browsertime/indexeddb_write.js`` under the ``testing/raptor/browsertime/`` directory
* Modify the test case script argument of ``commands.js.run`` / Selenium's ``executeAsyncScript``
* Test parameters can be passed to such script with syntax ``${variable_name}`` where ``variable_name`` represents the parameter in the context of ``executeAsyncScript`` or ``commands.js.run``.
* Use quotes to capture a string value, for example ``"${variable_name}"``
* TIP: Debugging the test case could be simpler by serving it locally without the boilerplate
* Add ``[test_name]`` section to file ``testing/raptor/raptor/tests/custom/browsertime-indexeddb.ini`` where ``test_name`` **must be 10 characters or less** in order to be a valid ``Treeherder`` test name
* Under the ``[test_name]`` section, specify the test script name as a value of ``test_script =``
* Under the ``[test_name]`` section, specity the test parameters as a sequence of ``--browsertime.key=value`` arguments as a value of ``browsertime_args =``
* Under the ``[test_name]`` section, override any other values as needed
* Add test as a subtest to run for Desktop ``taskcluster/ci/test/browsertime-desktop.yml`` (maybe also for mobile)
* Add test documentation to ``testing/raptor/raptor/perfdocs/config.yml``
* Generated files:
* Run ``./mach lint --warnings --outgoing --fix`` to regenerate the documentation and task files, and warn about omissions
* Running ``./mach lint -l perfdocs --fix .`` may also be needed
* Testing:
* Test the new test by running it with the profiler
* Test the new test by running it with a different browser
* Test the new test by triggering it on CI

Просмотреть файл

@ -802,3 +802,49 @@ browsertime-throttled:
run-on-projects: []
tier: 3
treeherder-symbol: Btime(throttled)
browsertime-indexeddb:
description: Raptor (browsertime) tests for IndexedDB
max-run-time: 2700
treeherder-symbol: Btime(idb)
limit-platforms:
by-app:
chrome:
- .*shippable.*
chromium:
- .*shippable.*
custom-car:
- .*64.*shippable.*
default: []
raptor:
apps: [firefox, chrome, chromium]
run-visual-metrics: false
subtests:
- addMab1
- addMabN
- addMar1
- addMarN
- addMbl1
- addMblN
- addkAB1
- addkABN
- addkAR1
- addkARN
- addkBL1
- addkBLN
- getkeyrng
run-on-projects:
by-app:
firefox:
by-test-platform:
windows.*-32.*: []
.*64.*shippable-qr/.*: [autoland, mozilla-central]
default: []
default: []
tier:
by-app:
firefox: 2
default: 3
mozharness:
extra-options:
- --extra-profiler-run

Просмотреть файл

@ -99,6 +99,7 @@ browsertime:
- browsertime-speculative
- browsertime-throttled
- browsertime-pageload-benchmark
- browsertime-indexeddb
browsertime-clang:
- browsertime-tp6

Просмотреть файл

@ -0,0 +1,66 @@
=============================
IndexedDB Performance Testing
=============================
How to run tests on CI:
-----------------------
* Windows: ``mach try perf --show-all -q "test-windows10-64-shippable-qr/opt-browsertime-indexeddb"``
* Linux: ``mach try perf --show-all -q "test-linux1804-64-shippable-qr/opt-browsertime-indexeddb"``
* Mac: ``mach try perf --show-all -q "test-macosx1015-64-shippable-qr/opt-browsertime-indexeddb"``
* All but 32-bit jobs: ``mach try perf --chrome --safari --show-all -q 'shippable-browsertime-indexeddb !32'``
* In general:
* Open test selection interface with ``mach try perf --show-all``
* Filter out the preferred tests by typing letters which are expected to be part of the test job name string (as in the -q argument above)
* Note down the string used as a filter for rerunning the job (or rerun it with ``mach try again --list-tasks`` and ``mach try again --index``)
How to run tests locally with the profiler?
-------------------------------------------
* Build the browser with release or release with debug symbols flags (not in debug mode)
* Use ``mach raptor --browsertime -t $(test_name) --gecko-profile --post-startup-delay=1000`` where test name, such as ``addMarN`` is one of the items listed in ``testing/raptor/raptor/tests/custom/browsertime-indexeddb.ini``
* After the test is complete, the generated profile is opened with the default browser.
* The generated profile file path is listed also in the command line output.
* For best symbolication results, it may help to
* run the same browser build that was used for the tests with ``./mach run``
* navigate to "profiler.firefox.com"
* use the "Load a profile from file" button
How to compare performance to a different browser?
--------------------------------------------------
* The test outputs a ``time_duration`` value for all supported browsers
* Using Chrome as an example,
* ``mach raptor --browsertime -t $(test_name) --post-startup-delay=1000 --app=chrome -b "/c/Program Files/Google/Chrome/Application/chrome.exe"``
* where test name, such as ``addMarN`` is one of the items listed in ``testing/raptor/raptor/tests/custom/browsertime-indexeddb.ini``
* browser executable path after the ``-b`` argument varies locally
* in some cases, a test driver argument such as ``--browsertime-chromedriver`` may be required
How to add more tests?
----------------------
* For the test boilerplate, copy and rename an old test script such as ``testing/raptor/browsertime/indexeddb_write.js`` under the ``testing/raptor/browsertime/`` directory
* Modify the test case script argument of ``commands.js.run`` / Selenium's ``executeAsyncScript``
* Test parameters can be passed to such script with syntax ``${variable_name}`` where ``variable_name`` represents the parameter in the context of ``executeAsyncScript`` or ``commands.js.run``.
* Use quotes to capture a string value, for example ``"${variable_name}"``
* TIP: Debugging the test case could be simpler by serving it locally without the boilerplate
* Add ``[test_name]`` section to file ``testing/raptor/raptor/tests/custom/browsertime-indexeddb.ini`` where ``test_name`` **must be 10 characters or less** in order to be a valid ``Treeherder`` test name
* Under the ``[test_name]`` section, specify the test script name as a value of ``test_script =``
* Under the ``[test_name]`` section, specity the test parameters as a sequence of ``--browsertime.key=value`` arguments as a value of ``browsertime_args =``
* Under the ``[test_name]`` section, override any other values as needed
* Add test as a subtest to run for Desktop ``taskcluster/ci/test/browsertime-desktop.yml`` (maybe also for mobile)
* Add test documentation to ``testing/raptor/raptor/perfdocs/config.yml``
* Generated files:
* Run ``./mach lint --warnings --outgoing --fix`` to regenerate the documentation and task files, and warn about omissions
* Running ``./mach lint -l perfdocs --fix .`` may also be needed
* Testing:
* Test the new test by running it with the profiler
* Test the new test by running it with a different browser
* Test the new test by triggering it on CI

Просмотреть файл

@ -8,6 +8,7 @@ Performance Testing
:glob:
DAMP
IndexedDB
awsy
fxrecord
mach-try-perf
@ -23,6 +24,7 @@ but `mozperftest </testing/perfdocs/mozperftest.html>`_ aims to provide this in
For more detailed information about each test suite and project, see their documentation:
* :doc:`DAMP`
* :doc:`IndexedDB`
* :doc:`awsy`
* :doc:`fxrecord`
* :doc:`mach-try-perf`

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,69 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint-env node */
module.exports = async function (context, commands) {
context.log.info("Starting a indexedDB getkeyrange");
const test_url = context.options.browsertime.url;
let page_cycles = context.options.browsertime.page_cycles;
let page_cycle_delay = context.options.browsertime.page_cycle_delay;
let post_startup_delay = context.options.browsertime.post_startup_delay;
context.log.info(
"Waiting for %d ms (post_startup_delay)",
post_startup_delay
);
await commands.wait.byTime(post_startup_delay);
await commands.navigate(test_url);
for (let count = 0; count < page_cycles; count++) {
context.log.info("Cycle %d, waiting for %d ms", count, page_cycle_delay);
await commands.wait.byTime(page_cycle_delay);
context.log.info("Cycle %d, starting the measure", count);
await await commands.measure.start();
await commands.js.run(`
const notifyDone = arguments[arguments.length - 1];
async function resPromise() {
return new Promise((resolve, reject) => {
const results = {};
const request = indexedDB.open('get-keyrange', 1);
request.onsuccess = () => {
const db = request.result;
const start = Date.now();
const keyRange = IDBKeyRange.bound(0, 99);
const transaction = db.transaction('entries', 'readonly');
const store = transaction.objectStore('entries');
const index = store.index('index');
const getAllRequest = index.getAll(keyRange);
getAllRequest.onsuccess = () => {
const items = getAllRequest.result;
items.forEach((item) => {
results[item.key] = item;
});
const end = Date.now();
db.close();
resolve(end - start);
};
getAllRequest.onerror = () => {
reject(getAllRequest.error);
};
};
});
}
resPromise().then(() => {
notifyDone();
});
`);
await commands.measure.stop();
}
context.log.info("IndexedDB getkeyrange ended.");
return true;
};

Просмотреть файл

@ -0,0 +1,153 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint-env node */
module.exports = async function (context, commands) {
context.log.info("Starting a indexedDB write");
const post_startup_delay = context.options.browsertime.post_startup_delay;
console.log("context options", context.options);
const test_url = context.options.browsertime.url;
const chunk_size = context.options.browsertime.chunk_size;
const iterations = context.options.browsertime.iterations;
const buffer_type = context.options.browsertime.buffer_type;
const atomic_value = context.options.browsertime.atomic;
if (atomic_value * atomic_value != atomic_value) {
throw Error("Value of atomic shall be 0 for falsehood, 1 for truth.");
}
const atomic = 0 != atomic_value;
const accepted_buffers = ["Array", "ArrayBuffer", "Blob"];
if (!accepted_buffers.includes(buffer_type)) {
throw Error("Buffer type " + buffer_type + " is unknown.");
}
context.log.info("IndexedDB write URL = " + test_url);
context.log.info("IndexedDB write chunk size = " + chunk_size);
context.log.info("IndexedDB write iterations = " + iterations);
context.log.info(
"IndexedDB writes " +
(atomic ? "all in one big transaction" : "in separate transactions")
);
context.log.info("IndexedDB write data format " + buffer_type);
context.log.info(
"Waiting for %d ms (post_startup_delay)",
post_startup_delay
);
await commands.navigate(test_url);
const seleniumDriver = context.selenium.driver;
await commands.wait.byTime(post_startup_delay);
await commands.measure.start();
const time_duration = await seleniumDriver.executeAsyncScript(`
const notifyDone = arguments[arguments.length - 1];
const iterations = ${iterations};
const sizeInBytes = ${chunk_size};
const bufferType = "${buffer_type}";
const atomic = ${atomic};
const makeData = (() => {
if (bufferType === "ArrayBuffer") {
return () => {
const valueBuffer = new ArrayBuffer(sizeInBytes);
const charCodeView = new Uint16Array(valueBuffer);
const sizeInUint16 = sizeInBytes / 2;
for (let i=0; i < sizeInUint16; ++i) {
charCodeView[i] = "qwerty".charCodeAt(i % 6);
}
return valueBuffer;
};
}
if (bufferType === "Array") {
return () => {
return Array.from({length: sizeInBytes}, (_, i) => "qwerty"[i % 6]);
};
}
if (bufferType !== "Blob") {
throw Error("Unknown buffer type " + bufferType);
}
return () => {
return new Blob([Array.from({length: sizeInBytes}, (_, i) => "qwerty"[i % 6])]);
};
})();
function addData(txSource, txProvider, i) {
try {
const keyName = "doc_" + i;
const valueData = makeData();
const record = { key: keyName, property: valueData };
const rq = txProvider(txSource).add(record);
return new Promise((res_ad, rej_ad) => {
rq.onsuccess = () => { res_ad(); };
rq.onerror = e => { rej_ad(e); };
});
} catch (e) {
return new Promise((_, rej_ad) => rej_ad(e));
}
}
function waitForData(txSource) {
try {
if (!atomic) {
const txProvider = src => src.transaction("store", "readwrite").objectStore("store");
return Promise.all(
Array.from({ length: iterations }, (_, i) => {
return addData(txSource, txProvider, i);
}));
}
const currentTx = txSource.transaction("store", "readwrite").objectStore("store");
return Promise.all(
Array.from({ length: iterations }, (_, i) => {
return addData(currentTx, src => src, i);
}));
} catch (e) {
return new Promise((_, rej_tx) => rej_tx(e));
}
}
function upgradePromise() {
try {
const open_db = indexedDB.open("rootsdb");
return new Promise((res_upgrade, rej_upgrade) => {
open_db.onupgradeneeded = e => {
e.target.result.createObjectStore("store", { keyPath: "key" });
};
open_db.onsuccess = e => { res_upgrade(e.target.result); };
open_db.onerror = e => { rej_upgrade(e); };
});
} catch (e) {
return new Promise((_, rej_upgrade) => rej_upgrade(e));
}
}
const startTime = performance.now();
upgradePromise().then(waitForData).then(() => {
notifyDone(performance.now() - startTime);
});
`);
await commands.measure.stop();
console.log("Time duration was ", time_duration);
await commands.measure.addObject({
custom_data: { time_duration },
});
context.log.info("IndexedDB write ended.");
return true;
};

Просмотреть файл

@ -164,7 +164,20 @@ suites:
process-switch: "Measures process switch time"
welcome: "Measures pageload metrics for the first-install about:welcome page"
grandprix: "Runs the Grandprix benchmark"
addMab1: "Use add API to send many small ArrayBuffers to IndexedDB in one transaction"
addMabN: "Use add API to send many small ArrayBuffers to IndexedDB independently"
addMar1: "Use add API to send many small Arrays to IndexedDB in one transaction"
addMarN: "Use add API to send many small Arrays to IndexedDB independently"
addMbl1: "Use add API to send many small Blobs to IndexedDB in one transaction"
addMblN: "Use add API to send many small Blobs to IndexedDB independently"
addkAB1: "Use add API to send a couple of large ArrayBuffers to IndexedDB in one transaction"
addkABN: "Use add API to send a couple of large ArrayBuffers to IndexedDB independently"
addkAR1: "Use add API to send a couple of large JS Arrays to IndexedDB in one transaction"
addkARN: "Use add API to send a couple of large JS Arrays to IndexedDB independently"
addkBL1: "Use add API to send a couple of large Blobs to IndexedDB in one transaction"
addkBLN: "Use add API to send a couple of large Blobs to IndexedDB independently"
constant-regression: "Generates a constant value that can be changed to induce a regression."
getkeyrng: "Measures the speed of key-range based reads of IndexedDB"
upload: "Measures http/2 file upload throughput"
upload-h3: "Measures http/3 file upload throughput"
throttled: "Pageload test using a throttled network environment"

Просмотреть файл

@ -71,3 +71,6 @@
# Custom throttled network pageload test
[include:tests/custom/browsertime-throttled-pageload.ini]
# Custom indexeddb test
[include:tests/custom/browsertime-indexeddb.ini]

Просмотреть файл

@ -0,0 +1,83 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
[DEFAULT]
apps = firefox, chrome, chromium, safari
alert_threshold = 2.0
browser_cycles = 1
custom_data = true
gecko_profile_entries = 131072000
gecko_profile_features = js,stackwalk,cpu
gecko_profile_threads = GeckoMain,DOM Worker,IndexedDB
lower_is_better = true
measure = cpuTime
output_timeout = 2000000
owner = DOM Lifecycle, Workers and Storage Team
page_cycles = 1
page_timeout = 1800000
subtest_unit = ms
test_summary = flatten
type = pageload
unit = ms
playback = mitmproxy
playback_pageset_manifest = mitm8-linux-firefox-example.manifest
test_url = https://www.example.com
use_live_sites = false
# Meaning of the idb_write names:
# 1. Iterations - how many add/put requests are made? (k ~ few, M ~ many)
# 2. Buffer type - what kind of buffer is supplied to each add/put, Array (ar), ArrayBuffer (ab) or Blob (bl)?
# 3. Chunk size - how much data is stored in each add/put? (lower-case buffer type: small, capitalized buffer type: a lot)
# 4. Transactions - should each add/put share one big transaction (1 => atomic=1) or have its own transaction (N => atomic=0)?
[addMab1]
browsertime_args = --browsertime.iterations=16384 --browsertime.chunk_size=1024 --browsertime.buffer_type=ArrayBuffer --browsertime.atomic=1
test_script = indexeddb_write.js
[addMabN]
browsertime_args = --browsertime.iterations=16384 --browsertime.chunk_size=1024 --browsertime.buffer_type=ArrayBuffer --browsertime.atomic=0
test_script = indexeddb_write.js
[addMar1]
browsertime_args = --browsertime.iterations=16384 --browsertime.chunk_size=1024 --browsertime.buffer_type=Array --browsertime.atomic=1
test_script = indexeddb_write.js
[addMarN]
browsertime_args = --browsertime.iterations=16384 --browsertime.chunk_size=1024 --browsertime.buffer_type=Array --browsertime.atomic=0
test_script = indexeddb_write.js
[addMbl1]
browsertime_args = --browsertime.iterations=16384 --browsertime.chunk_size=1024 --browsertime.buffer_type=Blob --browsertime.atomic=1
test_script = indexeddb_write.js
[addMblN]
browsertime_args = --browsertime.iterations=16384 --browsertime.chunk_size=1024 --browsertime.buffer_type=Blob --browsertime.atomic=0
test_script = indexeddb_write.js
[addkAB1]
browsertime_args = --browsertime.iterations=128 --browsertime.chunk_size=1048576 --browsertime.buffer_type=ArrayBuffer --browsertime.atomic=1
test_script = indexeddb_write.js
[addkABN]
browsertime_args = --browsertime.iterations=128 --browsertime.chunk_size=1048576 --browsertime.buffer_type=ArrayBuffer --browsertime.atomic=0
test_script = indexeddb_write.js
[addkAR1]
browsertime_args = --browsertime.iterations=128 --browsertime.chunk_size=1048576 --browsertime.buffer_type=Array --browsertime.atomic=1
test_script = indexeddb_write.js
[addkARN]
browsertime_args = --browsertime.iterations=128 --browsertime.chunk_size=1048576 --browsertime.buffer_type=Array --browsertime.atomic=0
test_script = indexeddb_write.js
[addkBL1]
browsertime_args = --browsertime.iterations=128 --browsertime.chunk_size=1048576 --browsertime.buffer_type=Blob --browsertime.atomic=1
test_script = indexeddb_write.js
[addkBLN]
browsertime_args = --browsertime.iterations=128 --browsertime.chunk_size=1048576 --browsertime.buffer_type=Blob --browsertime.atomic=0
test_script = indexeddb_write.js
[getkeyrng]
test_script = indexeddb_getkeyrange.js

Просмотреть файл

@ -9,6 +9,7 @@ perfdocs:
'testing/talos',
'testing/performance/fxrecord',
'testing/performance/mach-try-perf',
'dom/indexedDB/test',
]
exclude: []
extensions: ['rst', 'ini', 'yml']