v8/test/mjsunit/wasm/array-copy-benchmark.js

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

109 lines
3.8 KiB
JavaScript
Raw Normal View History

// 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
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, wasmOptRefType(struct_index)
var array_index = builder.addArray(array_type, true);
var from = builder.addGlobal(wasmOptRefType(array_index), true);
var to = builder.addGlobal(wasmOptRefType(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(kWasmI32, 2)
.addBody([
kExprLoop, kWasmVoid,
...wasmI32Const(0),
kExprLocalSet, 0,
kExprGlobalGet, from.index, kExprRefAsNonNull,
kExprGlobalGet, to.index, kExprRefAsNonNull,
kExprLet, kWasmVoid, 1, 2, kWasmRef, array_index,
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,
kExprEnd,
// Outer loop: run everything {iterations} times.
kExprLocalGet, 1, kExprI32Const, 1, kExprI32Add, kExprLocalSet, 1,
kExprLocalGet, 1, ...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");
}
})();