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

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: 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 var o = {};
76 o[s] = undefined;
77 return Object.keys(o)[0];
Toon Verwaest 2016/04/26 08:11:48 Object.keys({[s]:0})[0] :)
Igor Sheludko 2016/04/26 09:59:04 Done.
78 }
79
80 function Deinternalize(s) {
81 return [...s].join("");
82 }
83
84 // ============================================================================
85
86 const QUERY_INTERNALIZED_PROP = "query-internalized-prop";
87 const QUERY_DEINTERNALIZED_PROP = "query-deinternalized-prop";
88 const QUERY_NON_EXISTING_INTERNALIZED_PROP =
89 "query-non-existing-internalized-prop";
90 const QUERY_NON_EXISTING_DEINTERNALIZED_PROP =
91 "query-non-existing-deinternalized-prop";
92 const QUERY_ELEMENT = "query-element";
93 const QUERY_ELEMENT_AS_STRING = "query-element-as-string";
94 const QUERY_NON_EXISTING_ELEMENT = "query-non-existing-element";
95
96 const OBJ_MODE_FAST = "fast";
97 const OBJ_MODE_SLOW = "slow";
98
99 var TestQueries = [
100 QUERY_INTERNALIZED_PROP,
101 QUERY_DEINTERNALIZED_PROP,
102 QUERY_NON_EXISTING_INTERNALIZED_PROP,
103 QUERY_NON_EXISTING_DEINTERNALIZED_PROP,
104 QUERY_ELEMENT,
105 QUERY_ELEMENT_AS_STRING,
106 QUERY_NON_EXISTING_ELEMENT,
107 ];
108
109 const QUERIES_PER_OBJECT_NUMBER = 10;
110
111 // Leave only every "count"th keys.
112 function FilterKeys(keys, count) {
113 var len = keys.length;
114 if (len < count) throw new Error("Keys array is too short: " + len);
115 var step = len / count;
116 if (step == 0) throw new Error("Bad count specified: " + count);
117 return keys.filter((element, index) => index % step == 0);
118 }
119
120
121 function MakeKeyQueries(keys, query_kind) {
122 var properties = keys.filter((element) => isNaN(Number(element)));
123 var elements = keys.filter((element) => !isNaN(Number(element)));
124
125 properties = FilterKeys(properties, QUERIES_PER_OBJECT_NUMBER);
126 elements = FilterKeys(elements, QUERIES_PER_OBJECT_NUMBER);
127
128 switch (query_kind) {
129 case QUERY_INTERNALIZED_PROP:
130 return properties;
131
132 case QUERY_DEINTERNALIZED_PROP:
133 return properties.map(Deinternalize);
134
135 case QUERY_NON_EXISTING_INTERNALIZED_PROP:
136 case QUERY_NON_EXISTING_DEINTERNALIZED_PROP:
137 var non_existing = [];
138 for (var i = 0; i < QUERIES_PER_OBJECT_NUMBER; i++) {
139 non_existing.push("non-existing" + i);
140 }
141 if (query_kind == QUERY_NON_EXISTING_INTERNALIZED_PROP) {
142 return non_existing.map(Internalize);
143 } else {
144 return non_existing.map(Deinternalize);
145 }
146
147 case QUERY_ELEMENT:
148 return elements.map(Number);
149
150 case QUERY_ELEMENT_AS_STRING:
151 return elements.map(String);
152
153 case QUERY_NON_EXISTING_ELEMENT:
154 var non_existing = [];
155 for (var i = 0; i < QUERIES_PER_OBJECT_NUMBER; i++) {
156 non_existing.push(1200 + 100*i);
157 }
158 return non_existing;
159
160 default:
161 throw new Error("Bad query_kind: " + query_kind);
162 }
163 }
164
165
166 var TestData = [];
167
168 [true, false].forEach((cachable) => {
169 [OBJ_MODE_FAST, OBJ_MODE_SLOW].forEach((obj_mode) => {
170 var proto_mode = cachable ? "" : "-with-slow-proto";
171 var name = `${obj_mode}-obj${proto_mode}`;
172 var objects = [];
173 [10, 50, 100, 200, 500, 1000].forEach((prop_count) => {
174 // Create object with prop_count properties and prop_count elements.
175 obj = ObjectWithProtoKeys(5, prop_count * 2, cachable,
176 ObjectWithMixedKeys);
177 if (obj_mode == OBJ_MODE_SLOW) {
178 obj = MakeDictionaryMode(obj);
179 }
180 objects.push(obj);
181 });
182 TestData.push({name, objects});
183 });
184 });
185
186
187 // ============================================================================
188
189 function CreateTestFunction(template, object, keys) {
190 // Force a new function for each test-object to avoid side-effects due to ICs.
191 var text = "// random comment " + Math.random() + "\n" +
192 template(object, keys);
193 var func = new Function("object", "keys", text);
194 return () => func(object, keys);
195 }
196
197 var TestFunctions = [
198 {
199 name: "in",
200 // Query all keys.
201 keys: (object) => Object.keys(object),
202 template: (object, keys) => {
203 var lines = [
204 `var result = true;`,
205 `for (var i = 0; i < keys.length; i++) {`,
206 ` var key = keys[i];`,
207 ` result = (key in object) && result;`,
208 `}`,
209 `return result;`,
210 ];
211 return lines.join("\n");
212 },
213 },
214 {
215 name: "Object.hasOwnProperty",
216 // Query only own keys.
217 keys: (object) => Object.getOwnPropertyNames(object),
218 template: (object, keys) => {
219 var lines = [
220 `var result = true;`,
221 `for (var i = 0; i < keys.length; i++) {`,
222 ` var key = keys[i];`,
223 ` result = object.hasOwnProperty(key) && result;`,
224 `}`,
225 `return result;`,
226 ];
227 return lines.join("\n");
228 },
229 },
230 ];
231
232
233 // ============================================================================
234 // Create the benchmark suites. We create a suite for each pair of the test
235 // functions above and query kind. Each suite contains benchmarks for each
236 // object type.
237 var Benchmarks = [];
238
239 for (var test_function_desc of TestFunctions) {
240 var test_function_name = test_function_desc.name;
241
242 for (var query_kind of TestQueries) {
243 for (var test_data of TestData) {
244 var benchmarks = [];
245 var name = test_function_name + "--" + query_kind + "--" + test_data.name;
246
247 for (var object of test_data.objects) {
248 var keys = test_function_desc.keys(object);
249 keys = MakeKeyQueries(keys, query_kind);
250
251 var test_function = CreateTestFunction(test_function_desc.template,
252 object, keys);
253
254 var benchmark = new Benchmark(name, false, true, 400, test_function);
255 benchmarks.push(benchmark);
256 }
257 Benchmarks.push(new BenchmarkSuite(name, [100], benchmarks));
258 }
259 }
260 }
261
262 // ============================================================================
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