v8/test/mjsunit/wasm/array-copy-benchmark.js
Manos Koukoutos ccc74bc64e [wasm-gc] Remove 'let' opcode
This opcode is being removed in favor of pre-declared non-defaultable
locals (details are still TBD).

Bug: v8:9495
Change-Id: I96ac053a1b5a852310c5dc0bbaeab0cbf5384663
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3738743
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81496}
2022-07-01 14:35:09 +00:00

197 lines
7.0 KiB
JavaScript

// Copyright 2021 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-gc --no-liftoff --experimental-wasm-nn-locals
d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
// This is benchmark to investigate at which point it is more efficient to call
// a memcpy-based builtin for array.copy, rather than copying
// element-by-element.
// How to run:
// - Set {iterations} to a high number to get better measurements
// - Change the value of {length} to find point at which the builtin becomes
// faster.
// - Change {array_type} if you want to test different types.
// Right now, the limit is found to be around 10.
(function ArrayCopyBenchmark() {
let array_length = 10;
let iterations = 1;
var builder = new WasmModuleBuilder();
let struct_index = builder.addStruct([makeField(kWasmI32, true),
makeField(kWasmI8, false)]);
let array_type = kWasmI32; // Also try kWasmI64, wasmRefNullType(struct_index)
var array_index = builder.addArray(array_type, true);
var from = builder.addGlobal(wasmRefNullType(array_index), true);
var to = builder.addGlobal(wasmRefNullType(array_index), true);
builder.addFunction("init", kSig_v_v)
.addBody([
...wasmI32Const(array_length),
kGCPrefix, kExprRttCanon, array_index,
kGCPrefix, kExprArrayNewDefaultWithRtt, array_index,
kExprGlobalSet, from.index,
...wasmI32Const(array_length),
kGCPrefix, kExprRttCanon, array_index,
kGCPrefix, kExprArrayNewDefaultWithRtt, array_index,
kExprGlobalSet, to.index
])
.exportFunc();
builder.addFunction("array_copy", kSig_v_v)
.addLocals(kWasmI32, 1)
.addBody([
kExprLoop, kWasmVoid,
kExprGlobalGet, to.index,
...wasmI32Const(0),
kExprGlobalGet, from.index,
...wasmI32Const(0),
...wasmI32Const(array_length),
kGCPrefix, kExprArrayCopy, array_index, array_index,
// Outer loop: run everything {iterations} times.
kExprLocalGet, 0, kExprI32Const, 1, kExprI32Add, kExprLocalSet, 0,
kExprLocalGet, 0, ...wasmI32Const(iterations), kExprI32LtS,
kExprBrIf, 0,
kExprEnd])
.exportFunc();
builder.addFunction("loop_copy", kSig_v_v)
.addLocals(wasmRefType(array_index), 2)
.addLocals(kWasmI32, 2)
.addBody([
kExprLoop, kWasmVoid,
...wasmI32Const(0),
kExprLocalSet, 2,
kExprGlobalGet, from.index, kExprRefAsNonNull, kExprLocalSet, 0,
kExprGlobalGet, to.index, kExprRefAsNonNull, kExprLocalSet, 1,
kExprLoop, kWasmVoid,
kExprLocalGet, 1, // array
kExprLocalGet, 2, // index
// value
kExprLocalGet, 0, kExprLocalGet, 2,
kGCPrefix, kExprArrayGet, array_index,
// array.set
kGCPrefix, kExprArraySet, array_index,
// index++
kExprLocalGet, 2, kExprI32Const, 1, kExprI32Add, kExprLocalSet, 2,
// if (index < array_length) goto loop;
kExprLocalGet, 2, ...wasmI32Const(array_length), kExprI32LtU,
kExprBrIf, 0,
kExprEnd,
// Outer loop: run everything {iterations} times.
kExprLocalGet, 3, kExprI32Const, 3, kExprI32Add, kExprLocalSet, 3,
kExprLocalGet, 3, ...wasmI32Const(iterations), kExprI32LtS,
kExprBrIf, 0,
kExprEnd])
.exportFunc();
var instance = builder.instantiate({});
instance.exports.init();
print("Array length: " + array_length + ", #iterations: " + iterations);
{
let before = Date.now();
instance.exports.array_copy();
let after = Date.now();
print("array.copy: " + (after - before) + "ms");
}
{
let before = Date.now();
instance.exports.loop_copy();
let after = Date.now();
print("loop copy: " + (after - before) + "ms");
}
})();
// The following two benchmarks measure the efficiency of array allocation.
// Change the three first parameters of each benchmarks to measure different
// array sizes, iterations, and element types.
(function ArrayNewDefaultBenchmark() {
let array_length = 10;
let iterations = 1
let test_object_type = false;
var builder = new WasmModuleBuilder();
let struct_index = builder.addStruct([makeField(kWasmI32, true),
makeField(kWasmI8, false)]);
let array_type = test_object_type ? wasmRefNullType(struct_index) : kWasmI32;
var array_index = builder.addArray(array_type, true);
let array_new = builder.addFunction(
"array_new", makeSig([], [wasmRefNullType(array_index)]))
.addBody([
...wasmI32Const(array_length),
kGCPrefix, kExprRttCanon, array_index,
kGCPrefix, kExprArrayNewDefaultWithRtt, array_index])
.exportFunc();
builder.addFunction("loop_array_new", kSig_v_v)
.addLocals(wasmRefNullType(array_index), 1)
.addLocals(kWasmI32, 1)
.addBody([
kExprLoop, kWasmVoid,
kExprCallFunction, array_new.index,
kExprLocalSet, 0,
kExprLocalGet, 1, kExprI32Const, 1, kExprI32Add, kExprLocalTee, 1,
...wasmI32Const(iterations), kExprI32LtS,
kExprBrIf, 0,
kExprEnd])
.exportFunc();
var instance = builder.instantiate({});
print(`Type: ${test_object_type ? "object" : "i32"}, array length: ` +
`${array_length}, #iterations: ${iterations}`);
let before = Date.now();
instance.exports.loop_array_new();
let after = Date.now();
print(`array.new_default: ${after - before} ms`);
})();
(function ArrayNewBenchmark() {
let array_length = 10;
let iterations = 1;
let test_object_type = true;
var builder = new WasmModuleBuilder();
let struct_index = builder.addStruct([makeField(kWasmI32, true),
makeField(kWasmI8, false)]);
let array_type = test_object_type ? wasmRefNullType(struct_index) : kWasmI32;
var array_index = builder.addArray(array_type, true);
let array_new = builder.addFunction(
"array_new", makeSig([], [wasmRefNullType(array_index)]))
.addBody([
...(test_object_type ? [kGCPrefix, kExprStructNewDefault, struct_index]
: wasmI32Const(10)),
...wasmI32Const(array_length),
kGCPrefix, kExprRttCanon, array_index,
kGCPrefix, kExprArrayNewWithRtt, array_index])
.exportFunc();
builder.addFunction("loop_array_new", kSig_v_v)
.addLocals(wasmRefNullType(array_index), 1)
.addLocals(kWasmI32, 1)
.addBody([
kExprLoop, kWasmVoid,
kExprCallFunction, array_new.index,
kExprLocalSet, 0,
kExprLocalGet, 1, kExprI32Const, 1, kExprI32Add, kExprLocalTee, 1,
...wasmI32Const(iterations), kExprI32LtS,
kExprBrIf, 0,
kExprEnd])
.exportFunc();
var instance = builder.instantiate({});
print(`Type: ${test_object_type ? "object" : "i32"}, array length: ` +
`${array_length}, #iterations: ${iterations}`);
let before = Date.now();
instance.exports.loop_array_new();
let after = Date.now();
print(`array.new: ${after - before} ms`);
})();