Commit 7ed98981 authored by Marja Hölttä's avatar Marja Hölttä Committed by Commit Bot

[super] Rewrite perf tests

- Add tests comparing super property access to normal property access
- Shift the work so that the framework takes less time and the thing
we're trying to measure takes more time.
- Optimize / disable the optimization for the target function, not the
whole test framework.
- Reduce the amount of boilerplate code in the tests.

Bug: v8:9237
Change-Id: Idde133298c9b8ffb3d49945ef9c67f5039634598
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2536635Reviewed-by: 's avatarShu-yu Guo <syg@chromium.org>
Commit-Queue: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71196}
parent b7176976
This diff is collapsed.
// Copyright 2020 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('../base.js');
const BENCHMARK_NAME = arguments[0];
const TEST_TYPE = arguments[1];
const optimize_param = arguments[2];
let optimize;
if (optimize_param == "opt") {
optimize = true;
} else if (optimize_param == "noopt"){
optimize = false;
} else {
throw new Error("Test configuration error");
}
const DETERMINISTIC_RUNS = 1;
const LOCAL_ITERATIONS = 10000;
new BenchmarkSuite(BENCHMARK_NAME, [1000], [
new Benchmark(BENCHMARK_NAME, false, false, DETERMINISTIC_RUNS, runBenchmark)
]);
// Classes for monomorphic super property access.
class A { };
A.prototype.super_prop_a0 = 10;
A.prototype.super_prop_a1 = 10;
A.prototype.super_prop_a2 = 10;
A.prototype.super_prop_a3 = 10;
A.prototype.super_prop_a4 = 10;
A.prototype.super_prop_a5 = 10;
A.prototype.super_prop_a6 = 10;
A.prototype.super_prop_a7 = 10;
A.prototype.super_prop_a8 = 10;
A.prototype.super_prop_a9 = 10;
class B extends A { }
B.prototype.super_prop_b0 = 10;
B.prototype.super_prop_b1 = 10;
B.prototype.super_prop_b2 = 10;
B.prototype.super_prop_b3 = 10;
B.prototype.super_prop_b4 = 10;
B.prototype.super_prop_b5 = 10;
B.prototype.super_prop_b6 = 10;
B.prototype.super_prop_b7 = 10;
B.prototype.super_prop_b8 = 10;
B.prototype.super_prop_b9 = 10;
class C extends B {
test_super_a(unused) {
// Do many property accesses to increase the time taken by the thing we want
// to measure, in comparison to the overhead of calling this function.
return (super.super_prop_a0 + super.super_prop_a1 + super.super_prop_a2 +
super.super_prop_a3 + super.super_prop_a4 + super.super_prop_a5 +
super.super_prop_a6 + super.super_prop_a7 + super.super_prop_a8 +
super.super_prop_a9);
}
test_super_b(unused) {
return (super.super_prop_b0 + super.super_prop_b1 + super.super_prop_b2 +
super.super_prop_b3 + super.super_prop_b4 + super.super_prop_b5 +
super.super_prop_b6 + super.super_prop_b7 + super.super_prop_b8 +
super.super_prop_b9);
}
};
// Classes for megamorphic super property access.
function createClasses(base) {
class B extends base { };
B.prototype.super_prop_b0 = 10;
B.prototype.super_prop_b1 = 10;
B.prototype.super_prop_b2 = 10;
B.prototype.super_prop_b3 = 10;
B.prototype.super_prop_b4 = 10;
B.prototype.super_prop_b5 = 10;
B.prototype.super_prop_b6 = 10;
B.prototype.super_prop_b7 = 10;
B.prototype.super_prop_b8 = 10;
B.prototype.super_prop_b9 = 10;
class C extends B {
test_super_a(unused) {
return (super.super_prop_a0 + super.super_prop_a1 + super.super_prop_a2 +
super.super_prop_a3 + super.super_prop_a4 + super.super_prop_a5 +
super.super_prop_a6 + super.super_prop_a7 + super.super_prop_a8 +
super.super_prop_a9);
}
test_super_b(unused) {
return (super.super_prop_b0 + super.super_prop_b1 + super.super_prop_b2 +
super.super_prop_b3 + super.super_prop_b4 + super.super_prop_b5 +
super.super_prop_b6 + super.super_prop_b7 + super.super_prop_b8 +
super.super_prop_b9);
}
}
return C;
}
function test_property_access(o) {
return (o.prop0 + o.prop1 + o.prop2 + o.prop3 + o.prop4 + o.prop5 + o.prop6 +
o.prop7 + o.prop8 + o.prop9);
}
// Set up "objects" and "tested_functions" based on which test we're running.
let objects;
let tested_functions;
switch (TEST_TYPE) {
case "super_1":
// Monomorphic super property lookup, property is a constant, found 1 step
// above the lookup start object in the prototype chain.
objects = [new C()];
tested_functions = [C.prototype.test_super_a];
break;
case "normal_1":
// Monomorphic normal property lookup, property is a constant, found 1 step
// above the lookup start object in the prototype chain.
objects = [{__proto__: {"prop0": 10, "prop1": 10, "prop2": 10, "prop3": 10,
"prop4": 10, "prop5": 10, "prop6": 10, "prop7": 10,
"prop8": 10, "prop9": 10}}];
tested_functions = [test_property_access];
break;
case "super_2":
// Monomorphic super property lookup, property is a constant, found in the
// lookup start object.
objects = [new C()];
tested_functions = [C.prototype.test_super_b];
break;
case "normal_2":
// Monomorphic normal property lookup, property is a constant, found in the
// lookup start object.
objects = [{"prop0": 10, "prop1": 10, "prop2": 10, "prop3": 10, "prop4": 10,
"prop5": 10, "prop6": 10, "prop7": 10, "prop8": 10,
"prop9": 10}];
tested_functions = [test_property_access];
break;
case "super_3":
// Megamorphic super property lookup, property is a constant, found 1 step
// above the lookup start object in the prototype chain. The holder is
// the same in all cases though.
objects = [];
tested_functions = [];
for (let i = 0; i < 5; ++i) {
const c = createClasses(A);
objects.push(new c());
tested_functions.push(c.prototype.test_super_a);
}
break;
case "normal_3":
// Megamorphic normal property lookup, property is a constant, found 1 step
// above the lookup start object in the prototype chain. The holder is
// the same in all cases though.
const proto = {"prop0": 10, "prop1": 10, "prop2": 10, "prop3": 10,
"prop4": 10, "prop5": 10, "prop6": 10, "prop7": 10,
"prop8": 10, "prop9": 10};
objects = [{__proto__: proto}, {__proto__: proto, "a": 1},
{__proto__: proto, "a": 1, "b": 1},
{__proto__: proto, "a": 1, "b": 1, "c": 1},
{__proto__: proto, "a": 1, "b": 1, "c": 1, "d": 1}];
tested_functions = [test_property_access, test_property_access,
test_property_access, test_property_access,
test_property_access];
break;
case "super_4":
// Megamorphic super property lookup, property is a constant, found in the
// lookup start object. The holder is always a different object.
objects = [];
tested_functions = [];
for (let i = 0; i < 5; ++i) {
const c = createClasses(A);
objects.push(new c());
tested_functions.push(c.prototype.test_super_b);
}
break;
case "normal_4":
// Megamorphic normal property lookup, property is a constant, found in the
// lookup start object. The holder is always a different object.
objects = [{"prop0": 10, "prop1": 10, "prop2": 10, "prop3": 10, "prop4": 10,
"prop5": 10, "prop6": 10, "prop7": 10, "prop8": 10,
"prop9": 10},
{"a": 0, "prop0": 10, "prop1": 10, "prop2": 10, "prop3": 10,
"prop4": 10, "prop5": 10, "prop6": 10, "prop7": 10, "prop8": 10,
"prop9": 10},
{"a": 0, "b": 0, "prop0": 10, "prop1": 10, "prop2": 10,
"prop3": 10, "prop4": 10, "prop5": 10, "prop6": 10, "prop7": 10,
"prop8": 10, "prop9": 10},
{"a": 0, "b": 0, "c": 0, "prop0": 10, "prop1": 10, "prop2": 10,
"prop3": 10, "prop4": 10, "prop5": 10, "prop6": 10, "prop7": 10,
"prop8": 10, "prop9": 10},
{"a": 0, "b": 0, "c": 0, "d": 0, "prop0": 10, "prop1": 10,
"prop2": 10, "prop3": 10, "prop4": 10, "prop5": 10, "prop6": 10,
"prop7": 10, "prop8": 10, "prop9": 10}];
tested_functions = [test_property_access, test_property_access,
test_property_access, test_property_access,
test_property_access];
break;
default:
throw new Error("Test configuration error");
}
for (f of tested_functions) {
if (optimize) {
%PrepareFunctionForOptimization(f);
} else {
%NeverOptimizeFunction(f);
}
}
function runBenchmark() {
const expected_value = 10 * 10;
let ix = 0;
for (let i = 0; i < LOCAL_ITERATIONS; ++i) {
const object = objects[ix];
const r = tested_functions[ix].call(object, object);
if (r != expected_value) {
throw new Error("Test error");
}
if (++ix == objects.length) {
ix = 0;
if (optimize) {
for (f of tested_functions) {
%OptimizeFunctionOnNextCall(f);
}
}
}
}
}
var success = true;
function PrintResult(name, result) {
print(name + '(Score): ' + result);
}
function PrintError(name, error) {
PrintResult(name, error);
success = false;
}
BenchmarkSuite.config.doWarmup = false;
BenchmarkSuite.config.doDeterministic = true;
BenchmarkSuite.RunSuites({NotifyResult: PrintResult, NotifyError: PrintError});
// Copyright 2020 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.
const DETERMINISTIC_RUNS = 10000;
new BenchmarkSuite(BENCHMARK_NAME, [1000], [
new Benchmark(BENCHMARK_NAME, false, false, DETERMINISTIC_RUNS,
runBenchmark)
]);
function createSubclass() {
class A {
get super_prop() {
return 10;
}
};
class B extends A {
test() {
return super.super_prop;
}
};
return B;
}
const NO_CLASSES = 10;
let objects = [];
for (let i = 0; i < NO_CLASSES; ++i) {
const klass = createSubclass();
objects.push(new klass());
}
let ix = 0;
const EXPECTED_VALUE = 10;
function runBenchmark() {
const r = objects[ix].test();
if (r != EXPECTED_VALUE) {
throw new Error("Test error");
}
if (++ix == objects.length) {
ix = 0;
}
}
// Copyright 2020 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.
const DETERMINISTIC_RUNS = 10000;
new BenchmarkSuite(BENCHMARK_NAME, [1000], [
new Benchmark(BENCHMARK_NAME, false, false, DETERMINISTIC_RUNS,
runBenchmark)
]);
function createSubclass() {
class A { };
A.prototype.super_prop = 10;
class B extends A {
test() {
return super.super_prop;
}
};
return B;
}
const NO_CLASSES = 10;
let objects = [];
for (let i = 0; i < NO_CLASSES; ++i) {
const klass = createSubclass();
objects.push(new klass());
}
let ix = 0;
const EXPECTED_VALUE = 10;
function runBenchmark() {
const r = objects[ix].test();
if (r != EXPECTED_VALUE) {
throw new Error("Test error");
}
if (++ix == objects.length) {
ix = 0;
}
}
// Copyright 2020 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.
const DETERMINISTIC_RUNS = 10000;
new BenchmarkSuite(BENCHMARK_NAME, [1000], [
new Benchmark(BENCHMARK_NAME, false, false, DETERMINISTIC_RUNS, runBenchmark)
]);
class A {
get super_prop() {
return 10;
}
};
class B extends A {
test() {
return super.super_prop;
}
};
const objects = [new B(), new B(), new B(), new B()];
let ix = 0;
const EXPECTED_VALUE = 10;
function runBenchmark() {
const r = objects[ix].test();
if (r != EXPECTED_VALUE) {
throw new Error("Test error");
}
if (++ix == objects.length) {
ix = 0;
}
}
// Copyright 2020 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.
const DETERMINISTIC_RUNS = 10000;
new BenchmarkSuite(BENCHMARK_NAME, [1000], [
new Benchmark(BENCHMARK_NAME, false, false, DETERMINISTIC_RUNS, runBenchmark)
]);
class A {
get super_prop() {
return 10;
}
};
class B extends A {
test() {
return super.super_prop;
}
};
class C0 extends B { };
class C1 extends B { };
class C2 extends B { };
class C3 extends B { };
class C4 extends B { };
class C5 extends B { };
class C6 extends B { };
class C7 extends B { };
class C8 extends B { };
class C9 extends B { };
const objects = [
new C0(),
new C1(),
new C2(),
new C3(),
new C4(),
new C5(),
new C6(),
new C7(),
new C8(),
new C9(),
];
let ix = 0;
const EXPECTED_VALUE = 10;
function runBenchmark() {
const r = objects[ix].test();
if (r != EXPECTED_VALUE) {
throw new Error("Test error");
}
if (++ix == objects.length) {
ix = 0;
}
}
// Copyright 2020 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.
const DETERMINISTIC_RUNS = 10000;
new BenchmarkSuite(BENCHMARK_NAME, [1000], [
new Benchmark(BENCHMARK_NAME, false, false, DETERMINISTIC_RUNS,
runBenchmark)
]);
class A { };
A.prototype.super_prop = 10;
class B extends A {
test() {
return super.super_prop;
}
};
class C0 extends B { };
class C1 extends B { };
class C2 extends B { };
class C3 extends B { };
class C4 extends B { };
class C5 extends B { };
class C6 extends B { };
class C7 extends B { };
class C8 extends B { };
class C9 extends B { };
const objects = [
new C0(),
new C1(),
new C2(),
new C3(),
new C4(),
new C5(),
new C6(),
new C7(),
new C8(),
new C9(),
];
let ix = 0;
const EXPECTED_VALUE = 10;
function runBenchmark() {
const r = objects[ix].test();
if (r != EXPECTED_VALUE) {
throw new Error("Test error");
}
if (++ix == objects.length) {
ix = 0;
}
}
// Copyright 2020 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.
const DETERMINISTIC_RUNS = 10000;
new BenchmarkSuite(BENCHMARK_NAME, [1000], [
new Benchmark(BENCHMARK_NAME, false, false, DETERMINISTIC_RUNS, runBenchmark)
]);
class A { };
A.prototype.super_prop = 10;
class B extends A {
test() {
return super.super_prop;
}
};
const objects = [new B(), new B(), new B(), new B()];
let ix = 0;
const EXPECTED_VALUE = 10;
function runBenchmark() {
const r = objects[ix].test();
if (r != EXPECTED_VALUE) {
throw new Error("Test error");
}
if (++ix == objects.length) {
ix = 0;
}
}
// Copyright 2020 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.
const DETERMINISTIC_RUNS = 10000;
new BenchmarkSuite(BENCHMARK_NAME, [1000], [
new Benchmark(BENCHMARK_NAME, false, false, DETERMINISTIC_RUNS,
runBenchmark)
]);
function createSubclass() {
class A {
get super_prop() {
return 10;
}
};
class B extends A {
test() {
return super.super_prop;
}
};
return B;
}
const b1 = createSubclass();
const b2 = createSubclass();
const objects = [
new b1(),
new b2()
];
let ix = 0;
const EXPECTED_VALUE = 10;
function runBenchmark() {
const r = objects[ix].test();
if (r != EXPECTED_VALUE) {
throw new Error("Test error");
}
if (++ix == objects.length) {
ix = 0;
}
}
// Copyright 2020 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.
const DETERMINISTIC_RUNS = 10000;
new BenchmarkSuite(BENCHMARK_NAME, [1000], [
new Benchmark(BENCHMARK_NAME, false, false, DETERMINISTIC_RUNS, runBenchmark)
]);
function createSubclass() {
class A {
get super_prop() {
return 10;
}
};
class B extends A {
test() {
return super.super_prop;
}
};
return B;
}
const b1 = createSubclass();
const b2 = createSubclass();
class C0 extends b1 { };
class C1 extends b2 { };
class C2 extends b1 { };
class C3 extends b2 { };
class C4 extends b1 { };
class C5 extends b2 { };
class C6 extends b1 { };
class C7 extends b2 { };
class C8 extends b1 { };
class C9 extends b2 { };
const objects = [
new C0(),
new C1(),
new C2(),
new C3(),
new C4(),
new C5(),
new C6(),
new C7(),
new C8(),
new C9(),
];
let ix = 0;
const EXPECTED_VALUE = 10;
function runBenchmark() {
const r = objects[ix].test();
if (r != EXPECTED_VALUE) {
throw new Error("Test error");
}
if (++ix == objects.length) {
ix = 0;
}
}
// Copyright 2020 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.
const DETERMINISTIC_RUNS = 10000;
new BenchmarkSuite(BENCHMARK_NAME, [1000], [
new Benchmark(BENCHMARK_NAME, false, false, DETERMINISTIC_RUNS, runBenchmark)
]);
function createSubclass() {
class A { };
A.prototype.super_prop = 10;
class B extends A {
test() {
return super.super_prop;
}
};
return B;
}
const b1 = createSubclass();
const b2 = createSubclass();
class C0 extends b1 { };
class C1 extends b2 { };
class C2 extends b1 { };
class C3 extends b2 { };
class C4 extends b1 { };
class C5 extends b2 { };
class C6 extends b1 { };
class C7 extends b2 { };
class C8 extends b1 { };
class C9 extends b2 { };
const objects = [
new C0(),
new C1(),
new C2(),
new C3(),
new C4(),
new C5(),
new C6(),
new C7(),
new C8(),
new C9(),
];
let ix = 0;
const EXPECTED_VALUE = 10;
function runBenchmark() {
const r = objects[ix].test();
if (r != EXPECTED_VALUE) {
throw new Error("Test error");
}
if (++ix == objects.length) {
ix = 0;
}
}
// Copyright 2020 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.
const DETERMINISTIC_RUNS = 10000;
new BenchmarkSuite(BENCHMARK_NAME, [1000], [
new Benchmark(BENCHMARK_NAME, false, false, DETERMINISTIC_RUNS,
runBenchmark)
]);
function createSubclass() {
class A { };
A.prototype.super_prop = 10;
class B extends A {
test() {
return super.super_prop;
}
};
return B;
}
const b1 = createSubclass();
const b2 = createSubclass();
const objects = [
new b1(),
new b2()
];
let ix = 0;
const EXPECTED_VALUE = 10;
function runBenchmark() {
const r = objects[ix].test();
if (r != EXPECTED_VALUE) {
throw new Error("Test error");
}
if (++ix == objects.length) {
ix = 0;
}
}
// Copyright 2020 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('../base.js');
BENCHMARK_NAME = arguments[1];
load(arguments[0] + '.js');
var success = true;
function PrintResult(name, result) {
print(name + '(Score): ' + result);
}
function PrintError(name, error) {
PrintResult(name, error);
success = false;
}
BenchmarkSuite.config.doWarmup = false;
BenchmarkSuite.config.doDeterministic = true;
BenchmarkSuite.RunSuites({NotifyResult: PrintResult, NotifyError: PrintError});
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