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

Side by Side 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, 7 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 function ObjectWithKeys(count, keyOffset = 0, keyGen) {
6 var o = {};
7 for (var i = 0; i < count; i++) {
8 var key = keyGen(i + keyOffset);
9 o[key] = "value";
10 }
11 return o;
12 }
13
14 function ObjectWithProperties(count, keyOffset) {
15 return ObjectWithKeys(count, keyOffset, (key) => "key" + key );
16 }
17
18 function ObjectWithElements(count, keyOffset) {
19 return ObjectWithKeys(count, keyOffset, (key) => key );
20 }
21
22 function ObjectWithMixedKeys(count, keyOffset) {
23 return ObjectWithKeys(count, keyOffset, (key) => {
24 if (key % 2 == 0) return (key / 2);
25 return "key" + ((key - 1) / 2);
26 });
27 }
28
29 // Create an object with #depth prototypes each having #keys properties
30 // generated by given keyGen.
31 function ObjectWithProtoKeys(depth, keys, cacheable,
32 keyGen = ObjectWithProperties) {
33 var o = keyGen(keys);
34 var current = o;
35 var keyOffset = 0;
36 for (var i = 0; i < depth; i++) {
37 keyOffset += keys;
38 current.__proto__ = keyGen(keys, keyOffset);
39 current = current.__proto__;
40 }
41 if (cacheable === false) {
42 // Add an empty proxy at the prototype chain to make caching properties
43 // impossible.
44 current.__proto__ = new Proxy({}, {});
45 }
46 return o;
47 }
48
49
50 function HoleyIntArray(size) {
51 var array = new Array(size);
52 for (var i = 0; i < size; i += 3) {
53 array[i] = i;
54 }
55 return array
56 }
57
58 function IntArray(size) {
59 var array = new Array(size);
60 for (var i = 0; i < size; i++) {
61 array[i] = i;
62 }
63 return array;
64 }
65
66 // Switch object's properties and elements to dictionary mode.
67 function MakeDictionaryMode(obj) {
68 obj.foo = 0;
69 delete obj.foo;
70 obj[1e9] = 0;
71 return obj;
72 }
73
74 function Internalize(s) {
75 return Object.keys({[s]:0})[0];
76 }
77
78 function Deinternalize(s) {
79 return [...s].join("");
80 }
81
82 // ============================================================================
83
84 const QUERY_INTERNALIZED_PROP = "query-internalized-prop";
85 const QUERY_DEINTERNALIZED_PROP = "query-deinternalized-prop";
86 const QUERY_NON_EXISTING_INTERNALIZED_PROP =
87 "query-non-existing-internalized-prop";
88 const QUERY_NON_EXISTING_DEINTERNALIZED_PROP =
89 "query-non-existing-deinternalized-prop";
90 const QUERY_ELEMENT = "query-element";
91 const QUERY_ELEMENT_AS_STRING = "query-element-as-string";
92 const QUERY_NON_EXISTING_ELEMENT = "query-non-existing-element";
93
94 const OBJ_MODE_FAST = "fast";
95 const OBJ_MODE_SLOW = "slow";
96
97 var TestQueries = [
98 QUERY_INTERNALIZED_PROP,
99 QUERY_DEINTERNALIZED_PROP,
100 QUERY_NON_EXISTING_INTERNALIZED_PROP,
101 QUERY_NON_EXISTING_DEINTERNALIZED_PROP,
102 QUERY_ELEMENT,
103 QUERY_ELEMENT_AS_STRING,
104 QUERY_NON_EXISTING_ELEMENT,
105 ];
106
107 const QUERIES_PER_OBJECT_NUMBER = 10;
108
109 // Leave only every "count"th keys.
110 function FilterKeys(keys, count) {
111 var len = keys.length;
112 if (len < count) throw new Error("Keys array is too short: " + len);
113 var step = len / count;
114 if (step == 0) throw new Error("Bad count specified: " + count);
115 return keys.filter((element, index) => index % step == 0);
116 }
117
118
119 function MakeKeyQueries(keys, query_kind) {
120 var properties = keys.filter((element) => isNaN(Number(element)));
121 var elements = keys.filter((element) => !isNaN(Number(element)));
122
123 properties = FilterKeys(properties, QUERIES_PER_OBJECT_NUMBER);
124 elements = FilterKeys(elements, QUERIES_PER_OBJECT_NUMBER);
125
126 switch (query_kind) {
127 case QUERY_INTERNALIZED_PROP:
128 return properties;
129
130 case QUERY_DEINTERNALIZED_PROP:
131 return properties.map(Deinternalize);
132
133 case QUERY_NON_EXISTING_INTERNALIZED_PROP:
134 case QUERY_NON_EXISTING_DEINTERNALIZED_PROP:
135 var non_existing = [];
136 for (var i = 0; i < QUERIES_PER_OBJECT_NUMBER; i++) {
137 non_existing.push("non-existing" + i);
138 }
139 if (query_kind == QUERY_NON_EXISTING_INTERNALIZED_PROP) {
140 return non_existing.map(Internalize);
141 } else {
142 return non_existing.map(Deinternalize);
143 }
144
145 case QUERY_ELEMENT:
146 return elements.map(Number);
147
148 case QUERY_ELEMENT_AS_STRING:
149 return elements.map(String);
150
151 case QUERY_NON_EXISTING_ELEMENT:
152 var non_existing = [];
153 for (var i = 0; i < QUERIES_PER_OBJECT_NUMBER; i++) {
154 non_existing.push(1200 + 100*i);
155 }
156 return non_existing;
157
158 default:
159 throw new Error("Bad query_kind: " + query_kind);
160 }
161 }
162
163
164 var TestData = [];
165
166 [true, false].forEach((cachable) => {
167 [OBJ_MODE_FAST, OBJ_MODE_SLOW].forEach((obj_mode) => {
168 var proto_mode = cachable ? "" : "-with-slow-proto";
169 var name = `${obj_mode}-obj${proto_mode}`;
170 var objects = [];
171 [10, 50, 100, 200, 500, 1000].forEach((prop_count) => {
172 // Create object with prop_count properties and prop_count elements.
173 obj = ObjectWithProtoKeys(5, prop_count * 2, cachable,
174 ObjectWithMixedKeys);
175 if (obj_mode == OBJ_MODE_SLOW) {
176 obj = MakeDictionaryMode(obj);
177 }
178 objects.push(obj);
179 });
180 TestData.push({name, objects});
181 });
182 });
183
184
185 // ============================================================================
186
187 function CreateTestFunction(template, object, keys) {
188 // Force a new function for each test-object to avoid side-effects due to ICs.
189 var text = "// random comment " + Math.random() + "\n" +
190 template(object, keys);
191 var func = new Function("object", "keys", text);
192 return () => func(object, keys);
193 }
194
195 var TestFunctions = [
196 {
197 name: "in",
198 // Query all keys.
199 keys: (object) => Object.keys(object),
200 template: (object, keys) => {
201 var lines = [
202 `var result = true;`,
203 `for (var i = 0; i < keys.length; i++) {`,
204 ` var key = keys[i];`,
205 ` result = (key in object) && result;`,
206 `}`,
207 `return result;`,
208 ];
209 return lines.join("\n");
210 },
211 },
212 {
213 name: "Object.hasOwnProperty",
214 // Query only own keys.
215 keys: (object) => Object.getOwnPropertyNames(object),
216 template: (object, keys) => {
217 var lines = [
218 `var result = true;`,
219 `for (var i = 0; i < keys.length; i++) {`,
220 ` var key = keys[i];`,
221 ` result = object.hasOwnProperty(key) && result;`,
222 `}`,
223 `return result;`,
224 ];
225 return lines.join("\n");
226 },
227 },
228 ];
229
230
231 // ============================================================================
232 // Create the benchmark suites. We create a suite for each pair of the test
233 // functions above and query kind. Each suite contains benchmarks for each
234 // object type.
235 var Benchmarks = [];
236
237 for (var test_function_desc of TestFunctions) {
238 var test_function_name = test_function_desc.name;
239
240 for (var query_kind of TestQueries) {
241 for (var test_data of TestData) {
242 var benchmarks = [];
243 var name = test_function_name + "--" + query_kind + "--" + test_data.name;
244
245 for (var object of test_data.objects) {
246 var keys = test_function_desc.keys(object);
247 keys = MakeKeyQueries(keys, query_kind);
248
249 var test_function = CreateTestFunction(test_function_desc.template,
250 object, keys);
251
252 var benchmark = new Benchmark(name, false, true, 400, test_function);
253 benchmarks.push(benchmark);
254 }
255 Benchmarks.push(new BenchmarkSuite(name, [100], benchmarks));
256 }
257 }
258 }
259
260 // ============================================================================
OLDNEW
« 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