Commit 031d0698 authored by Ting Shao's avatar Ting Shao Committed by Commit Bot

Add Cache Storage API performance test for service worker

This change adds tests for measuring the performance of open, add,
and delete APIs of Cache Storage. Also adds support for running tests
in workers.

Design doc: https://docs.google.com/document/d/1bGBWHAsIsrQ0hrjU7oEVAcGSBS9gFSPcDL9nVWXDeeE/edit

Bug: 1019097
Change-Id: Ib173c699cda3ae9984ff20500e81b666b49d4e35
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1935928
Commit-Queue: Ting Shao <ting.shao@intel.com>
Reviewed-by: default avatarMatt Falkenhagen <falken@chromium.org>
Reviewed-by: default avatarMakoto Shimazu <shimazu@chromium.org>
Reviewed-by: default avatarCaleb Rouleau <crouleau@chromium.org>
Cr-Commit-Position: refs/heads/master@{#729667}
parent 4319a6eb
......@@ -147,6 +147,25 @@ Example of tracing asynchronous tests:
[simple-blob-measure-async.html](https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/perf_tests/test_data/simple-blob-measure-async.html)
### Service Worker Perf Tests
You can also run perf tests in service workers. You need to trigger the test
with `PerfTestRunner.startMeasureValuesInWorker()` in a page. Within the `run`
method provided to this function, you can initialize a worker and ask the
worker to run the workload by using `measureRunsPerSecond()` defined in
[worker-test-helper.js](https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/perf_tests/resources/worker-test-helper.js).
`measureRunsPerSecond()` returns a promise which resolves to the test result.
The worker should send the result back to the page, and the page records the
result by `PerfTestRunner.recordResultFromWorker()`. After the result is
recorded, the test finishes.
Here is an example for testing Cache Storage API of service workers:
[cache-open-add-delete-10K-service-worker.html](https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/perf_tests/service_worker/cache-open-add-delete-10K-service-worker.html)
[cache-open-add-delete-10K-service-worker.js](https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/perf_tests/service_worker/resources/cache-open-add-delete-10K-service-worker.js)
## Canvas Tests
The sub-framework [canvas_runner.js](https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/perf_tests/canvas/resources/canvas_runner.js) is used for
......
......@@ -177,7 +177,12 @@ if (window.testRunner) {
if (test.warmUpCount && test.warmUpCount > 0)
completedIterations = -test.warmUpCount;
logLines = PerfTestRunner.bufferedLog || window.testRunner ? [] : null;
PerfTestRunner.log("Running " + iterationCount + " times");
// Tests that run in workers are not impacted by the iteration control.
if (!currentTest.runInWorker) {
PerfTestRunner.log("Running " + iterationCount + " times");
}
if (test.doNotIgnoreInitialRun)
completedIterations++;
......@@ -245,7 +250,8 @@ if (window.testRunner) {
function ignoreWarmUpAndLog(measuredValue) {
var labeledResult = measuredValue + " " + PerfTestRunner.unit;
if (completedIterations <= 0)
// Tests that run in workers are not impacted by the iteration control.
if (!currentTest.runInWorker && completedIterations <= 0)
PerfTestRunner.log("Ignoring warm-up run (" + labeledResult + ")");
else {
results.push(measuredValue);
......@@ -454,5 +460,41 @@ if (window.testRunner) {
PerfTestRunner.measureTime(test);
}
// Used for tests that run in workers.
// 1. Call this method to trigger the test. It should be used together
// with |WorkerTestHelper.measureRunsPerSecond()| which is defined in
// src/third_party/blink/perf_tests/resources/worker-test-helper.js.
// 2. The iteration control parameters (test.iterationCount,
// test.doNotIgnoreInitialRun, and test.warmUpCount) are ignored.
// Use parameters of |measureRunsPerSecond()| to control iteration.
// 3. Test result should be sent to the page where the test is triggered.
// Then the result should be recorded by |recordResultFromWorker()| to
// finish the test.
PerfTestRunner.startMeasureValuesInWorker = function (test) {
PerfTestRunner.unit = test.unit;
test.runInWorker = true;
start(test, undefined, function() { test.run(); });
}
// Used for tests that run in workers.
// This method records the result posted from worker thread and finishes the test.
PerfTestRunner.recordResultFromWorker = function(result) {
if (result.error) {
PerfTestRunner.logFatalError(result.error);
return;
}
try {
result.values.forEach((value) => {
ignoreWarmUpAndLog(value);
});
} catch (exception) {
PerfTestRunner.logFatalError("Got an exception while logging the result with name=" + exception.name + ", message=" + exception.message);
return;
}
finish();
}
window.PerfTestRunner = PerfTestRunner;
})();
// This file defines helper methods for running performance tests in workers.
(function () {
class WorkerTestHelper {
constructor() {
this.callsPerIteration = 1;
}
// Measure the runs per second of test.run().
// This method should be used together with
// |PerfTestRunner.startMeasureValuesInWorker| in
// src/third_party/blink/perf_tests/resources/runner.js.
//
// Arguments:
// |test.run| is the function to test.
// |test.setup| and |test.tearDown| are optional functions.
// |test.iterationCount| defines count of iterations to run. Default value
// is 5.
//
// Returns a promise that resolves to an object:
// |result.error|: The error string or null if no error occurs.
// |result.values|: An array of test result values.
async measureRunsPerSecond(test) {
this.test = test;
const values = [];
const iterationCount =
this.test.iterationCount ? this.test.iterationCount : 5;
try {
if (this.test.setup)
await this.test.setup();
for (let i = 0; i < iterationCount; i++) {
values.push(await this.measureRunsPerSecondOnce_());
}
if (this.test.tearDown)
await this.test.tearDown();
} catch (exception) {
const error = "Got an exception while running test with name=" +
exception.name + ", message=" + exception.message + "\n" +
exception.stack;
return { error: error, values: null };
}
return { error: null, values: values };
}
// This method is basically the same with measureRunsPerSecondOnce() in
// src/third_party/blink/perf_tests/resources/runner.js
async measureRunsPerSecondOnce_() {
const timeToRun = 750;
let totalTime = 0;
let numberOfRuns = 0;
while (totalTime < timeToRun) {
totalTime += await this.callRunAndMeasureTime_();
numberOfRuns += this.callsPerIteration;
if (totalTime < 100)
this.callsPerIteration = Math.max(10, 2 * this.callsPerIteration);
}
return numberOfRuns * 1000 / totalTime;
};
async callRunAndMeasureTime_() {
var startTime = performance.now();
for (let i = 0; i < this.callsPerIteration; i++) {
await this.test.run();
}
return performance.now() - startTime;
}
}
self.workerTestHelper = new WorkerTestHelper();
})();
<!DOCTYPE html>
<html>
<head>
<script src='../resources/runner.js'></script>
</head>
<body>
<script>
function runTest() {
navigator.serviceWorker.addEventListener('message', (msg) => {
PerfTestRunner.recordResultFromWorker(msg.data);
});
const script =
'/service_worker/resources/cache-open-add-delete-10K-service-worker.js';
const scope = '/service_worker/resources/';
navigator.serviceWorker.register(script, { scope: scope }).catch((error) => {
PerfTestRunner.logFatalError(
'Failed to register service worker script:' + script);
});
return;
}
PerfTestRunner.startMeasureValuesInWorker({
description: 'Measure performance of open, add and delete operations of' +
'cache with 10K sized file',
unit: 'runs/s',
run: runTest,
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<script src='../resources/runner.js'></script>
</head>
<body>
<script>
function runTest() {
navigator.serviceWorker.addEventListener('message', (msg) => {
PerfTestRunner.recordResultFromWorker(msg.data);
});
const script =
'/service_worker/resources/cache-open-add-delete-1M-service-worker.js';
const scope = '/service_worker/resources/';
navigator.serviceWorker.register(script, { scope: scope }).catch((error) => {
PerfTestRunner.logFatalError(
'Failed to register service worker script:' + script);
});
return;
}
PerfTestRunner.startMeasureValuesInWorker({
description: 'Measure performance of open, add and delete operations of' +
' cache with 1M sized file',
unit: 'runs/s',
run: runTest,
});
</script>
</body>
</html>
importScripts('/resources/worker-test-helper.js');
// Send the result to all clients to finish the test.
function sendTestResultToClients(result) {
clients.matchAll({includeUncontrolled: true}).then((allClients) => {
for (const client of allClients) {
client.postMessage(result);
}
});
}
const CACHE_NAME = 'test-cache';
async function cacheOpenAddDelete() {
const cache = await caches.open(CACHE_NAME);
await cache.add('/service_worker/resources/data/10K.txt');
await cache.delete(CACHE_NAME);
}
async function test() {
const result = await self.workerTestHelper.measureRunsPerSecond({
run: cacheOpenAddDelete
});
sendTestResultToClients(result);
}
self.addEventListener('install', function(event) {
event.waitUntil(test());
});
importScripts('/resources/worker-test-helper.js');
// Send the result to all clients to finish the test.
function sendTestResultToClients(result) {
clients.matchAll({includeUncontrolled: true}).then((allClients) => {
for (const client of allClients) {
client.postMessage(result);
}
});
}
const CACHE_NAME = 'test-cache';
async function cacheOpenAddDelete() {
const cache = await caches.open(CACHE_NAME);
await cache.add('/service_worker/resources/data/1M.txt');
await cache.delete(CACHE_NAME);
}
async function test() {
const result = await self.workerTestHelper.measureRunsPerSecond({
run: cacheOpenAddDelete
});
sendTestResultToClients(result);
}
self.addEventListener('install', function(event) {
event.waitUntil(test());
});
AUTOGENERATED FILE DO NOT EDIT
See https://bit.ly/update-benchmarks-info to make changes
Benchmark name,Individual owners,Component,Documentation,Tags
UNSCHEDULED_blink_perf.service_worker,"shimazu@chromium.org, falken@chromium.org, ting.shao@intel.com",Blink>ServiceWorker,https://bit.ly/blink-perf-benchmarks,
angle_perftests,"jmadill@chromium.org, chrome-gpu-perf-owners@chromium.org",Internals>GPU>ANGLE,,
base_perftests,"skyostil@chromium.org, gab@chromium.org",Internals>SequenceManager,https://chromium.googlesource.com/chromium/src/+/HEAD/base/README.md#performance-testing,
blink_perf.accessibility,dmazzoni@chromium.org,Blink>Accessibility,https://bit.ly/blink-perf-benchmarks,
......
......@@ -4,8 +4,8 @@
from __future__ import print_function
import os
import collections
import os
from core import path_util
from core import perf_benchmark
......@@ -14,6 +14,7 @@ from page_sets import webgl_supported_shared_state
from telemetry import benchmark
from telemetry import page as page_module
from telemetry.core import memory_cache_http_server
from telemetry.page import legacy_page_test
from telemetry.page import shared_page_state
from telemetry import story
......@@ -393,6 +394,40 @@ class BlinkPerfBindings(_BlinkPerfBenchmark):
return 'blink_perf.bindings'
class ServiceWorkerRequestHandler(
memory_cache_http_server.MemoryCacheDynamicHTTPRequestHandler):
"""This handler returns dynamic responses for service worker perf tests.
"""
_SIZE_10K = 10240
_SIZE_1M = 1048576
def ResponseFromHandler(self, path):
if path.endswith('/service_worker/resources/data/10K.txt'):
return self.MakeResponse('c' * self._SIZE_10K, 'text/plain', False)
elif path.endswith('/service_worker/resources/data/1M.txt'):
return self.MakeResponse('c' * self._SIZE_1M, 'text/plain', False)
return None
@benchmark.Info(
component='Blink>ServiceWorker',
emails=[
'shimazu@chromium.org', 'falken@chromium.org', 'ting.shao@intel.com'
],
documentation_url='https://bit.ly/blink-perf-benchmarks')
class BlinkPerfServiceWorker(_BlinkPerfBenchmark):
SUBDIR = 'service_worker'
@classmethod
def Name(cls):
return 'UNSCHEDULED_blink_perf.service_worker'
def CreateStorySet(self, options):
story_set = super(BlinkPerfServiceWorker, self).CreateStorySet(options)
story_set.SetRequestHandlerClass(ServiceWorkerRequestHandler)
return story_set
@benchmark.Info(emails=['futhark@chromium.org', 'andruud@chromium.org'],
documentation_url='https://bit.ly/blink-perf-benchmarks',
component='Blink>CSS')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment