94f0abf98a
In order to track certain critical code-patters we will start adding micro-benchmarks that reflect common requests on http://jsperf.com. In this first CL a number of property enumeration methods are added, in the hope to get a clearer picture on future regressions. BUG= Review URL: https://codereview.chromium.org/1702613002 Cr-Commit-Position: refs/heads/master@{#34425}
210 lines
6.1 KiB
JavaScript
210 lines
6.1 KiB
JavaScript
// Copyright 2016 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 ObjectWithKeys(count, keyOffset, keyGen) {
|
|
if (keyOffset === undefined) keyOffset = 0;
|
|
if (keyGen === undefined) keyGen = (i) => { return "key" + i };
|
|
var o = {};
|
|
for (var i = 0; i < count; i++) {
|
|
var key = keyGen(i + keyOffset);
|
|
o[key] = "value";
|
|
}
|
|
return o
|
|
}
|
|
|
|
function ObjectWithMixedKeys(count, keyOffset) {
|
|
return ObjectWithKeys(count, keyOffset, (key) => {
|
|
if (key % 2 == 0) return key;
|
|
return "key" + key;
|
|
});
|
|
}
|
|
|
|
// Create an object with #depth prototypes each having #keys properties.
|
|
function ObjectWithProtoKeys(depth, keys, cacheable) {
|
|
var o = ObjectWithKeys(keys);
|
|
var current = o;
|
|
var keyOffset = 0;
|
|
for (var i = 0; i < depth; i++) {
|
|
keyOffset += keys;
|
|
current.__proto__ = ObjectWithKeys(keys, keyOffset);
|
|
current = current.__proto__;
|
|
}
|
|
if (cacheable === false) {
|
|
// Add an empty proxy at the prototype chain to make caching properties
|
|
// impossible.
|
|
current.__proto__ = new Proxy({}, {});
|
|
}
|
|
return o;
|
|
}
|
|
|
|
function HoleyIntArray(size) {
|
|
var array = new Array(size);
|
|
for (var i = 0; i < size; i += 3) {
|
|
array[i] = i;
|
|
}
|
|
return array
|
|
}
|
|
|
|
function IntArray(size) {
|
|
var array = new Array(size);
|
|
for (var i = 0; i < size; i++) {
|
|
array[i] = i;
|
|
}
|
|
return array;
|
|
}
|
|
|
|
// ============================================================================
|
|
var object_empty = {};
|
|
var array_empty = [];
|
|
|
|
var array_int_50 = IntArray(50);
|
|
var array_int_50_proto_elements = IntArray(50);
|
|
array_int_50_proto_elements.__proto__ = [51, 52, 53, 54];
|
|
var array_int_holey_50 = HoleyIntArray(50);
|
|
|
|
var empty_proto_5_10 = ObjectWithKeys(5);
|
|
empty_proto_5_10.__proto__ = ObjectWithProtoKeys(10, 0);
|
|
|
|
var empty_proto_5_5_slow = ObjectWithKeys(5);
|
|
empty_proto_5_5_slow.__proto__ = ObjectWithProtoKeys(5, 0, false);
|
|
|
|
var object_elements_proto_5_10 = ObjectWithKeys(5);
|
|
object_elements_proto_5_10.__proto__ = ObjectWithProtoKeys(10, 0);
|
|
// Add some properties further up the prototype chain, the rest stays
|
|
// empty.
|
|
for (var i = 0; i < 5; i++) {
|
|
object_elements_proto_5_10.__proto__.__proto__.__proto__["proto" + i] = true;
|
|
}
|
|
|
|
var TestObjects = {
|
|
object_empty: object_empty,
|
|
array_empty: array_empty,
|
|
array_int_50: array_int_50,
|
|
array_int_holey_50: array_int_holey_50,
|
|
array_int_50_proto_elements: array_int_50_proto_elements,
|
|
empty_proto_5_10: empty_proto_5_10,
|
|
empty_proto_5_5_slow: empty_proto_5_5_slow,
|
|
object_elements_proto_5_10: object_elements_proto_5_10
|
|
}
|
|
|
|
var TestArrays = {
|
|
array_empty: array_empty,
|
|
array_int_50: array_int_50,
|
|
array_int_holey_50: array_int_holey_50,
|
|
array_int_50_proto_elements: array_int_50_proto_elements,
|
|
}
|
|
|
|
// ============================================================================
|
|
|
|
function CreateTestFunctionGen(fn) {
|
|
// Force a new function for each test-object to avoid side-effects due to ICs.
|
|
return (object) => {
|
|
var random_comment = "\n// random comment" + Math.random() + "\n";
|
|
return eval(random_comment + fn.toString());
|
|
}
|
|
}
|
|
|
|
var TestFunctions = {
|
|
"Object.keys()": CreateTestFunctionGen(() => {return Object.keys(object)}),
|
|
"for-in": CreateTestFunctionGen(() => {
|
|
var count = 0;
|
|
var result;
|
|
for (var key in object) {
|
|
count++;
|
|
result = object[key];
|
|
};
|
|
return [result, count];
|
|
}),
|
|
"for-in hasOwnProperty()": CreateTestFunctionGen(() => {
|
|
var count = 0;
|
|
var result;
|
|
for (var key in object) {
|
|
if (!object.hasOwnProperty(key)) continue;
|
|
count++;
|
|
result = object[key];
|
|
};
|
|
return [result, count];
|
|
}),
|
|
"for (i < Object.keys().length)": CreateTestFunctionGen(() => {
|
|
var count = 0;
|
|
var result;
|
|
var keys = Object.keys(object);
|
|
for (var i = 0; i < keys.length; i++) {
|
|
count++;
|
|
result = object[keys[i]];
|
|
};
|
|
return [result, count];
|
|
}),
|
|
"Object.keys().forEach()": CreateTestFunctionGen(() => {
|
|
var count = 0;
|
|
var result;
|
|
Object.keys(object).forEach((value, index, obj) => {
|
|
count++;
|
|
result = value;
|
|
});
|
|
return [result, count];
|
|
}),
|
|
}
|
|
|
|
var TestFunctionsArrays = {
|
|
"for (i < array.length)": CreateTestFunctionGen(() => {
|
|
var count = 0;
|
|
var result;
|
|
for (var i = 0; i < object.length; i++) {
|
|
count++;
|
|
result = object[i];
|
|
};
|
|
return [result, count];
|
|
}),
|
|
"for (i < length)": CreateTestFunctionGen(() => {
|
|
var count = 0;
|
|
var result;
|
|
var length = object.length;
|
|
for (var i = 0; i < length; i++) {
|
|
count++;
|
|
result = object[i];
|
|
};
|
|
return [result, count];
|
|
})
|
|
}
|
|
|
|
// ============================================================================
|
|
// Create the benchmark suites. We create a suite for each of the test
|
|
// functions above and each suite contains benchmarks for each object type.
|
|
var Benchmarks = [];
|
|
|
|
function NewBenchmark(
|
|
test_function_gen, test_function_name, test_object, test_object_name) {
|
|
var object = test_object;
|
|
var name = test_function_name + " " + test_object_name;
|
|
var test_function = test_function_gen(object);
|
|
return new Benchmark(name, false, false, 0, test_function)
|
|
}
|
|
|
|
for (var test_function_name in TestFunctions) {
|
|
var test_function_gen = TestFunctions[test_function_name];
|
|
var benchmarks = [];
|
|
for (var test_object_name in TestObjects) {
|
|
var test_object = TestObjects[test_object_name];
|
|
var benchmark = NewBenchmark(
|
|
test_function_gen, test_function_name, test_object, test_object_name);
|
|
benchmarks.push(benchmark);
|
|
}
|
|
Benchmarks.push(new BenchmarkSuite(test_function_name, [100], benchmarks));
|
|
}
|
|
|
|
for (var test_function_name in TestFunctionsArrays) {
|
|
var test_function_gen = TestFunctionsArrays[test_function_name];
|
|
var benchmarks = [];
|
|
for (var test_array_name in TestArrays) {
|
|
var test_array = TestArrays[test_array_name];
|
|
var benchmark = NewBenchmark(
|
|
test_function_gen, test_function_name, test_array, test_array_name);
|
|
benchmarks.push(benchmark);
|
|
}
|
|
Benchmarks.push(new BenchmarkSuite(test_function_name, [100], benchmarks));
|
|
}
|
|
|
|
// ============================================================================
|