Commit b00386f9 authored by cbruni's avatar cbruni Committed by Commit bot

[js-perf-test] Adding micro benchmarks for for-in and keys patterns.

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@{#34364}
parent f8eb4e69
......@@ -135,6 +135,22 @@
"tests": [
{"name": "Try-Catch"}
]
},
{
"name": "Keys",
"path": ["Keys"],
"main": "run.js",
"resources": ["keys.js"],
"results_regexp": "^%s\\-Keys\\(Score\\): (.+)$",
"tests": [
{"name": "Object.keys()"},
{"name": "for (in)"},
{"name": "for (in) hasOwnProperty()"},
{"name": "for Object.keys()"},
{"name": "Object.keys().forEach()"},
{"name": "for (i < array.length)"},
{"name": "for (i < length)"}
]
}
]
}
// Copyright 2015 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_100 = IntArray(100);
var array_int_100_proto_elements = IntArray(100);
array_int_100_proto_elements.__proto__ = [101, 102, 103, 104];
var array_int_holey_100 = HoleyIntArray(100);
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_100: array_int_100,
array_int_holey_100: array_int_holey_100,
array_int_100_proto_elements: array_int_100_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_100: array_int_100,
array_int_holey_100: array_int_holey_100,
array_int_100_proto_elements: array_int_100_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];
})
}
// ============================================================================
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, [1000], 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, [1000], benchmarks));
}
// ============================================================================
// Copyright 2014 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');
load('keys.js');
var success = true;
function PrintResult(name, result) {
print(name + '-Keys(Score): ' + result);
}
function PrintError(name, error) {
PrintResult(name, error);
success = false;
}
BenchmarkSuite.config.doWarmup = undefined;
BenchmarkSuite.config.doDeterministic = undefined;
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