Commit 00e7df79 authored by Ting Shao's avatar Ting Shao Committed by Commit Bot

Add more Cache Storage API performance tests

Add perf tests to cover more Cache Storage APIs and also extend
WorkerTestHelper to support measuring time in worker.

All the Cache Storage perf tests cost 33 seconds on a machine:
CPU: Intel Core i7-4790 @ 3.6 GHZ
RAM: 32G

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

Bug: 1019097
Change-Id: I0c5adb9524d75dd8a7d84e10a14ef55a3b941473
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2008191
Commit-Queue: Ting Shao <ting.shao@intel.com>
Reviewed-by: default avatarCaleb Rouleau <crouleau@chromium.org>
Reviewed-by: default avatarMakoto Shimazu <shimazu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#748109}
parent 4ae08737
......@@ -264,7 +264,9 @@ if (window.testRunner) {
function finish() {
try {
console.timeEnd("blink_perf");
// The blink_perf timer is only started for non-worker test.
if (!currentTest.runInWorker)
console.timeEnd("blink_perf");
if (currentTest.description)
PerfTestRunner.log("Description: " + currentTest.description);
PerfTestRunner.logStatistics(results, PerfTestRunner.unit, "Time:");
......@@ -484,6 +486,7 @@ if (window.testRunner) {
return;
}
PerfTestRunner.log("Running " + result.values.length + " times");
try {
result.values.forEach((value) => {
ignoreWarmUpAndLog(value);
......
......@@ -19,8 +19,29 @@
//
// 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.
// |result.values|: An array of test result values. Unit is runs/s.
async measureRunsPerSecond(test) {
return await this.runTestRepeatedly_(test,
this.measureRunsPerSecondOnce_.bind(this));
}
// Measure the elapsed time of test.run().
// This method should be used together with
// |PerfTestRunner.startMeasureValuesInWorker| in
// src/third_party/blink/perf_tests/resources/runner.js.
//
// Refer measureRunsPerSecond() for definition of the arguments.
//
// 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. Unit is ms.
async measureTime(test) {
return await this.runTestRepeatedly_(test,
this.callRunAndMeasureTime_.bind(this));
}
// Repeatedly run test.run() and measure it.
async runTestRepeatedly_(test, proc) {
this.test = test;
const values = [];
const iterationCount =
......@@ -30,7 +51,7 @@
if (this.test.setup)
await this.test.setup();
for (let i = 0; i < iterationCount; i++) {
values.push(await this.measureRunsPerSecondOnce_());
values.push(await proc());
}
if (this.test.tearDown)
await this.test.tearDown();
......@@ -60,7 +81,7 @@
};
async callRunAndMeasureTime_() {
var startTime = performance.now();
const startTime = performance.now();
for (let i = 0; i < this.callsPerIteration; i++) {
await this.test.run();
}
......
<!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-has-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 CacheStorage.has().',
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-keys-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 Cache.keys().',
unit: 'ms',
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-matchAll-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 Cache.matchAll().',
unit: 'ms',
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);
}
});
}
async function setup() {
for (let i = 0; i < 100; i++) {
const cache = await caches.open(`test_cache_${i}`);
await cache.add(`/service_worker/resources/data/1K_${i}.txt`);
}
}
async function cacheStorageHas() {
await caches.has('test_cache_50');
await caches.has('test_cache_101');
}
async function test() {
const result = await self.workerTestHelper.measureRunsPerSecond({
setup: setup,
run: cacheStorageHas,
});
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 FILES = [];
for (let i = 0; i < 100; i++) {
FILES.push(`/service_worker/resources/data/1K_${i}.txt`);
}
let cache = null;
async function setup() {
cache = await caches.open('test-cache');
await cache.addAll(FILES);
}
async function cacheKeys() {
await cache.keys();
}
async function test() {
const result = await self.workerTestHelper.measureTime({
setup: setup,
run: cacheKeys,
iterationCount: 10
});
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 FILES = [];
for (let i = 0; i < 100; i++) {
FILES.push(`/service_worker/resources/data/1K_${i}.txt`);
}
let cache = null;
async function setup() {
cache = await caches.open('test-cache');
await cache.addAll(FILES);
}
async function cacheMatchAll() {
await cache.matchAll();
}
async function test() {
const result = await self.workerTestHelper.measureTime({
setup: setup,
run: cacheMatchAll,
iterationCount: 10
});
sendTestResultToClients(result);
}
self.addEventListener('install', function(event) {
event.waitUntil(test());
});
......@@ -6,6 +6,7 @@ from __future__ import print_function
import collections
import os
import re
from core import path_util
from core import perf_benchmark
......@@ -399,14 +400,21 @@ class ServiceWorkerRequestHandler(
memory_cache_http_server.MemoryCacheDynamicHTTPRequestHandler):
"""This handler returns dynamic responses for service worker perf tests.
"""
_SIZE_1K = 1024
_SIZE_10K = 10240
_SIZE_1M = 1048576
_FILE_NAME_PATTERN_1K =\
re.compile('.*/service_worker/resources/data/1K_[0-9]+\\.txt')
def ResponseFromHandler(self, path):
if path.endswith('/service_worker/resources/data/10K.txt'):
# normalize the path by replacing backslashes with slashes.
normpath = path.replace('\\', '/')
if normpath.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'):
elif normpath.endswith('/service_worker/resources/data/1M.txt'):
return self.MakeResponse('c' * self._SIZE_1M, 'text/plain', False)
elif self._FILE_NAME_PATTERN_1K.match(normpath):
return self.MakeResponse('c' * self._SIZE_1K, 'text/plain', False)
return None
......
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