Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(346)

Unified Diff: test/js-perf-test/PropertyQueries/property-queries.js

Issue 1913813003: [js-perf-test] Add microbenchmarks for in operator and Object.prototype.hasOwnProperty(). (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addressing comments Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « test/js-perf-test/PropertyQueries/PropertyQueries.json ('k') | test/js-perf-test/PropertyQueries/run.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/js-perf-test/PropertyQueries/property-queries.js
diff --git a/test/js-perf-test/PropertyQueries/property-queries.js b/test/js-perf-test/PropertyQueries/property-queries.js
new file mode 100644
index 0000000000000000000000000000000000000000..8c5498bd6569a55b8bec84c7beca8173ba03fe43
--- /dev/null
+++ b/test/js-perf-test/PropertyQueries/property-queries.js
@@ -0,0 +1,260 @@
+// 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 = 0, keyGen) {
+ var o = {};
+ for (var i = 0; i < count; i++) {
+ var key = keyGen(i + keyOffset);
+ o[key] = "value";
+ }
+ return o;
+}
+
+function ObjectWithProperties(count, keyOffset) {
+ return ObjectWithKeys(count, keyOffset, (key) => "key" + key );
+}
+
+function ObjectWithElements(count, keyOffset) {
+ return ObjectWithKeys(count, keyOffset, (key) => key );
+}
+
+function ObjectWithMixedKeys(count, keyOffset) {
+ return ObjectWithKeys(count, keyOffset, (key) => {
+ if (key % 2 == 0) return (key / 2);
+ return "key" + ((key - 1) / 2);
+ });
+}
+
+// Create an object with #depth prototypes each having #keys properties
+// generated by given keyGen.
+function ObjectWithProtoKeys(depth, keys, cacheable,
+ keyGen = ObjectWithProperties) {
+ var o = keyGen(keys);
+ var current = o;
+ var keyOffset = 0;
+ for (var i = 0; i < depth; i++) {
+ keyOffset += keys;
+ current.__proto__ = keyGen(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;
+}
+
+// Switch object's properties and elements to dictionary mode.
+function MakeDictionaryMode(obj) {
+ obj.foo = 0;
+ delete obj.foo;
+ obj[1e9] = 0;
+ return obj;
+}
+
+function Internalize(s) {
+ return Object.keys({[s]:0})[0];
+}
+
+function Deinternalize(s) {
+ return [...s].join("");
+}
+
+// ============================================================================
+
+const QUERY_INTERNALIZED_PROP = "query-internalized-prop";
+const QUERY_DEINTERNALIZED_PROP = "query-deinternalized-prop";
+const QUERY_NON_EXISTING_INTERNALIZED_PROP =
+ "query-non-existing-internalized-prop";
+const QUERY_NON_EXISTING_DEINTERNALIZED_PROP =
+ "query-non-existing-deinternalized-prop";
+const QUERY_ELEMENT = "query-element";
+const QUERY_ELEMENT_AS_STRING = "query-element-as-string";
+const QUERY_NON_EXISTING_ELEMENT = "query-non-existing-element";
+
+const OBJ_MODE_FAST = "fast";
+const OBJ_MODE_SLOW = "slow";
+
+var TestQueries = [
+ QUERY_INTERNALIZED_PROP,
+ QUERY_DEINTERNALIZED_PROP,
+ QUERY_NON_EXISTING_INTERNALIZED_PROP,
+ QUERY_NON_EXISTING_DEINTERNALIZED_PROP,
+ QUERY_ELEMENT,
+ QUERY_ELEMENT_AS_STRING,
+ QUERY_NON_EXISTING_ELEMENT,
+];
+
+const QUERIES_PER_OBJECT_NUMBER = 10;
+
+// Leave only every "count"th keys.
+function FilterKeys(keys, count) {
+ var len = keys.length;
+ if (len < count) throw new Error("Keys array is too short: " + len);
+ var step = len / count;
+ if (step == 0) throw new Error("Bad count specified: " + count);
+ return keys.filter((element, index) => index % step == 0);
+}
+
+
+function MakeKeyQueries(keys, query_kind) {
+ var properties = keys.filter((element) => isNaN(Number(element)));
+ var elements = keys.filter((element) => !isNaN(Number(element)));
+
+ properties = FilterKeys(properties, QUERIES_PER_OBJECT_NUMBER);
+ elements = FilterKeys(elements, QUERIES_PER_OBJECT_NUMBER);
+
+ switch (query_kind) {
+ case QUERY_INTERNALIZED_PROP:
+ return properties;
+
+ case QUERY_DEINTERNALIZED_PROP:
+ return properties.map(Deinternalize);
+
+ case QUERY_NON_EXISTING_INTERNALIZED_PROP:
+ case QUERY_NON_EXISTING_DEINTERNALIZED_PROP:
+ var non_existing = [];
+ for (var i = 0; i < QUERIES_PER_OBJECT_NUMBER; i++) {
+ non_existing.push("non-existing" + i);
+ }
+ if (query_kind == QUERY_NON_EXISTING_INTERNALIZED_PROP) {
+ return non_existing.map(Internalize);
+ } else {
+ return non_existing.map(Deinternalize);
+ }
+
+ case QUERY_ELEMENT:
+ return elements.map(Number);
+
+ case QUERY_ELEMENT_AS_STRING:
+ return elements.map(String);
+
+ case QUERY_NON_EXISTING_ELEMENT:
+ var non_existing = [];
+ for (var i = 0; i < QUERIES_PER_OBJECT_NUMBER; i++) {
+ non_existing.push(1200 + 100*i);
+ }
+ return non_existing;
+
+ default:
+ throw new Error("Bad query_kind: " + query_kind);
+ }
+}
+
+
+var TestData = [];
+
+[true, false].forEach((cachable) => {
+ [OBJ_MODE_FAST, OBJ_MODE_SLOW].forEach((obj_mode) => {
+ var proto_mode = cachable ? "" : "-with-slow-proto";
+ var name = `${obj_mode}-obj${proto_mode}`;
+ var objects = [];
+ [10, 50, 100, 200, 500, 1000].forEach((prop_count) => {
+ // Create object with prop_count properties and prop_count elements.
+ obj = ObjectWithProtoKeys(5, prop_count * 2, cachable,
+ ObjectWithMixedKeys);
+ if (obj_mode == OBJ_MODE_SLOW) {
+ obj = MakeDictionaryMode(obj);
+ }
+ objects.push(obj);
+ });
+ TestData.push({name, objects});
+ });
+});
+
+
+// ============================================================================
+
+function CreateTestFunction(template, object, keys) {
+ // Force a new function for each test-object to avoid side-effects due to ICs.
+ var text = "// random comment " + Math.random() + "\n" +
+ template(object, keys);
+ var func = new Function("object", "keys", text);
+ return () => func(object, keys);
+}
+
+var TestFunctions = [
+ {
+ name: "in",
+ // Query all keys.
+ keys: (object) => Object.keys(object),
+ template: (object, keys) => {
+ var lines = [
+ `var result = true;`,
+ `for (var i = 0; i < keys.length; i++) {`,
+ ` var key = keys[i];`,
+ ` result = (key in object) && result;`,
+ `}`,
+ `return result;`,
+ ];
+ return lines.join("\n");
+ },
+ },
+ {
+ name: "Object.hasOwnProperty",
+ // Query only own keys.
+ keys: (object) => Object.getOwnPropertyNames(object),
+ template: (object, keys) => {
+ var lines = [
+ `var result = true;`,
+ `for (var i = 0; i < keys.length; i++) {`,
+ ` var key = keys[i];`,
+ ` result = object.hasOwnProperty(key) && result;`,
+ `}`,
+ `return result;`,
+ ];
+ return lines.join("\n");
+ },
+ },
+];
+
+
+// ============================================================================
+// Create the benchmark suites. We create a suite for each pair of the test
+// functions above and query kind. Each suite contains benchmarks for each
+// object type.
+var Benchmarks = [];
+
+for (var test_function_desc of TestFunctions) {
+ var test_function_name = test_function_desc.name;
+
+ for (var query_kind of TestQueries) {
+ for (var test_data of TestData) {
+ var benchmarks = [];
+ var name = test_function_name + "--" + query_kind + "--" + test_data.name;
+
+ for (var object of test_data.objects) {
+ var keys = test_function_desc.keys(object);
+ keys = MakeKeyQueries(keys, query_kind);
+
+ var test_function = CreateTestFunction(test_function_desc.template,
+ object, keys);
+
+ var benchmark = new Benchmark(name, false, true, 400, test_function);
+ benchmarks.push(benchmark);
+ }
+ Benchmarks.push(new BenchmarkSuite(name, [100], benchmarks));
+ }
+ }
+}
+
+// ============================================================================
« no previous file with comments | « test/js-perf-test/PropertyQueries/PropertyQueries.json ('k') | test/js-perf-test/PropertyQueries/run.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698