Commit 4a416dbb authored by Ben L. Titzer's avatar Ben L. Titzer Committed by Commit Bot

[mjsunit] Add more tests for shared array buffers / memories

This CL adds more stress-tests for both shared array buffers and
WebAssembly memories. Because of an existing memory leak that will
be fixed in upcoming CLs, some new tests are disabled.

R=mstarzinger@chromium.org
BUG=v8:9380

Change-Id: I2662e3d0a764a032a0c267b2d99e3ccd1a4951d0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1697252
Commit-Queue: Ben Titzer <titzer@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62770}
parent d79a77fb
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function Alloc(size) {
let b = new SharedArrayBuffer(size);
let v = new Int32Array(b);
return {buffer : b, view : v};
}
function RunSomeAllocs(total, retained, size) {
print(`-------iterations = ${total}, retained = $ { retained } -------`);
var array = new Array(retained);
for (var i = 0; i < total; i++) {
if ((i % 25) == 0)
print(`iteration $ { i }`);
let pair = Alloc(size);
// For some iterations, retain the memory, view, or both.
switch (i % 3) {
case 0:
pair.memory = null;
break;
case 1:
pair.view = null;
break;
case 2:
break;
}
array[i % retained] = pair;
}
}
RunSomeAllocs(10, 1, 1024);
RunSomeAllocs(100, 3, 2048);
RunSomeAllocs(1000, 10, 16384);
RunSomeAllocs(10000, 20, 32768);
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
load("test/mjsunit/worker-ping-test.js");
let config = {
numThings: 4, // size of circular buffer
numWorkers: 4, // number of workers
numMessages: 10000, // number of messages sent to each worker
allocInterval: 11, // interval for allocating new things per worker
traceScript: false, // print the script
traceAlloc: false, // print each allocation attempt
traceIteration: 10, // print diagnostics every so many iterations
abortOnFail: true, // kill worker if allocation fails
AllocThing: function AllocThing(id) {
return new SharedArrayBuffer(10000);
},
}
RunWorkerPingTest(config);
......@@ -57,6 +57,9 @@
# Issue 8505: Math.pow is incorrect for asm.js
'regress/wasm/regress-8505': [SKIP],
# Issue 9380: Memory leaks of shared WebAssembly.Memory objects
'wasm/shared-memory-worker-gc': [SKIP],
##############################################################################
# Too slow in debug mode with --stress-opt mode.
'regress/regress-create-exception': [PASS, ['mode == debug', SKIP]],
......
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function AllocMemory(pages, max = pages) {
let m =
new WebAssembly.Memory({initial : pages, maximum : max, shared : true});
let v = new Int32Array(m.buffer);
return {memory : m, view : v};
}
function RunSomeAllocs(total, retained, pages, max = pages) {
print(`-------iterations = ${total}, retained = $ { retained } -------`);
var array = new Array(retained);
for (var i = 0; i < total; i++) {
if ((i % 25) == 0)
print(`iteration $ { i }`);
let pair = AllocMemory(pages, max);
// For some iterations, retain the memory, view, or both.
switch (i % 3) {
case 0:
pair.memory = null;
break;
case 1:
pair.view = null;
break;
case 2:
break;
}
array[i % retained] = pair;
}
}
RunSomeAllocs(10, 1, 1, 1);
RunSomeAllocs(100, 3, 1, 1);
RunSomeAllocs(1000, 10, 1, 1);
RunSomeAllocs(10000, 20, 1, 1);
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --experimental-wasm-threads --expose-gc
load("test/mjsunit/worker-ping-test.js");
let kDisabledAbort = false; // TODO(9380): enable abort for this test
let config = {
numThings: 4, // size of circular buffer
numWorkers: 4, // number of workers
numMessages: 500, // number of messages sent to each worker
allocInterval: 11, // interval for allocating new things per worker
traceScript: false, // print the script
traceAlloc: true, // print each allocation attempt
traceIteration: 10, // print diagnostics every so many iterations
abortOnFail: kDisabledAbort, // kill worker if allocation fails
AllocThing: function AllocThing(id) {
let pages = 1, max = 1;
return new WebAssembly.Memory({initial : pages, maximum : max, shared : true});
},
BeforeSend: function BeforeSend(msg) {
gc();
},
BeforeReceive: function BeforeReceive(msg) {
gc();
}
}
RunWorkerPingTest(config);
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --experimental-wasm-threads
load("test/mjsunit/worker-ping-test.js");
let kDisabledAbort = false; // TODO(9380): enable abort for this test
let config = {
numThings: 4, // size of circular buffer
numWorkers: 4, // number of workers
numMessages: 1000, // number of messages sent to each worker
allocInterval: 11, // interval for allocating new things per worker
traceScript: false, // print the script
traceAlloc: true, // print each allocation attempt
traceIteration: 10, // print diagnostics every so many iterations
abortOnFail: kDisabledAbort, // kill worker if allocation fails
AllocThing: function AllocThing(id) {
let pages = 1, max = 1;
return new WebAssembly.Memory({initial : pages, maximum : max, shared : true});
},
}
RunWorkerPingTest(config);
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --experimental-wasm-threads
const kNumMessages = 5000;
function AllocMemory(pages = 1, max = pages) {
return new WebAssembly.Memory({initial : pages, maximum : max, shared : true});
}
(function RunTest() {
let worker = new Worker(
`onmessage =
function(msg) {
if (msg.memory) postMessage({memory : msg.memory});
}`, {type : 'string'});
let time = performance.now();
for (let i = 0; i < kNumMessages; i++) {
let now = performance.now();
print(`iteration ${i}, Δ = ${(now - time).toFixed(3)} ms`);
time = now;
let memory = AllocMemory();
worker.postMessage({memory : memory});
let msg = worker.getMessage();
if (msg.memory) {
assertInstanceof(msg.memory, WebAssembly.Memory);
}
}
})();
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --experimental-wasm-threads
load("test/mjsunit/worker-ping-test.js");
let config = {
numThings: 4, // size of circular buffer
numWorkers: 4, // number of workers
numMessages: 2000, // number of messages sent to each worker
allocInterval: 10001, // interval for allocating new things per worker
traceScript: false, // print the script
traceAlloc: true, // print each allocation attempt
traceIteration: 10, // print diagnostics every so many iterations
abortOnFail: true, // kill worker if allocation fails
AllocThing: function AllocThing(id) {
let pages = 1, max = 1;
return new WebAssembly.Memory({initial : pages, maximum : max, shared : true});
},
}
RunWorkerPingTest(config);
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// A test utility for pinging objects back and forth among a pool of workers.
// Use by calling {RunWorkerPingTest} with a {config} object.
{
// Reference config object for demonstrating the interface.
let config = {
numThings: 4, // size of circular buffer
numWorkers: 4, // number of workers
numMessages: 100, // number of messages sent to each worker
allocInterval: 11, // interval for allocating new things per worker
traceScript: false, // print the script
traceAlloc: false, // print each allocation attempt
traceIteration: 10, // print diagnostics every so many iterations
abortOnFail: false, // kill worker if allocation fails
// Note that because the functions are appended to a worker script
// *as source*, they need to be named properly.
// The function that allocates things. Required.
AllocThing: function AllocThing(id) {
return new Array(2);
},
// Before message send behavior. Optional.
BeforeSend: function BeforeSend(msg) { },
// Before message reception behavior. Optional.
BeforeReceive: function BeforeReceive(msg) { },
}
}
function RunWorkerPingTest(config) {
let workers = [];
let beforeSend = (typeof config.BeforeSend == "function") ?
config.BeforeSend :
function BeforeSend(msg) { };
let beforeReceive = (typeof config.BeforeReceive == "function") ?
config.BeforeReceive :
function BeforeReceive(msg) { };
// Each worker has a circular buffer of size {config.numThings}, recording
// received things into the buffer and responding with a previous thing.
// Every {config.allocInterval}, a worker creates a new thing by
// {config.AllocThing}.
let script =
`const kNumThings = ${config.numThings};
const kAllocInterval = ${config.allocInterval};
let index = 0;
let total = 0;
let id = 0;
let things = new Array(kNumThings);
for (let i = 0; i < kNumThings; i++) {
things[i] = TryAllocThing();
}
function TryAllocThing() {
try {
let thing = AllocThing(id++);
${config.traceAlloc ? "print(\"alloc success\");" : ""}
return thing;
} catch(e) {
${config.abortOnFail ? "postMessage({error: e.toString()}); throw e;" : "" }
${config.traceAlloc ? "print(\"alloc fail: \" + e);" : ""}
}
}
onmessage = function(msg) {
BeforeReceive(msg);
if (msg.thing !== undefined) {
let reply = things[index];
if ((total % kAllocInterval) == 0) {
reply = TryAllocThing();
}
things[index] = msg.thing;
postMessage({thing : reply});
index = (index + 1) % kNumThings;
total++;
}
}
${config.AllocThing.toString()}
${beforeReceive.toString()}
`;
if (config.traceScript) {
print("========== Worker script ==========");
print(script);
print("===================================");
}
for (let i = 0; i < config.numWorkers; i++) {
let worker = new Worker(script, {type : 'string'});
workers.push(worker);
}
let time = performance.now();
// The main thread posts {config.numMessages} messages to {config.numWorkers}
// workers, with each message containing a "thing" created by {config.AllocThing}.
let thing = config.AllocThing(-1);
for (let i = 0; i < config.numMessages; i++) {
if ((i % config.traceIteration) == 0) {
let now = performance.now();
print(`iteration ${i}, Δ = ${(now - time).toFixed(3)} ms`);
time = now;
}
for (let worker of workers) {
let msg = {thing: thing};
beforeSend(msg);
worker.postMessage(msg);
msg = worker.getMessage();
if (msg.thing) {
thing = msg.thing;
} else if (msg.error) {
worker.terminate();
throw msg.error;
}
}
}
for (let worker of workers) {
worker.terminate();
}
}
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