|
1 <!DOCTYPE html> |
|
2 <html> |
|
3 <head> |
|
4 <title>js perf</title> |
|
5 <meta name="viewport" content="width=device-width,initial-scale=1.0"/> |
|
6 <meta charset="utf-8"/> |
|
7 |
|
8 <script src="board.js"></script> |
|
9 <script src="perf.js"></script> |
|
10 |
|
11 <style> |
|
12 body { |
|
13 width: 100%; |
|
14 } |
|
15 h1, div.area { |
|
16 text-align: center; |
|
17 margin: 10px auto; |
|
18 } |
|
19 #board { |
|
20 margin: 10px auto; |
|
21 } |
|
22 #board td { |
|
23 width: 40px; |
|
24 height: 40px; |
|
25 border: 1px solid red; |
|
26 margin: 0; |
|
27 text-align: center; |
|
28 } |
|
29 |
|
30 .test { |
|
31 border: 1px red dotted; |
|
32 } |
|
33 .report { |
|
34 border: 1px green dotted; |
|
35 } |
|
36 </style> |
|
37 |
|
38 </head> |
|
39 <body> |
|
40 |
|
41 <table id="board"> |
|
42 <tr> |
|
43 <td></td> |
|
44 <td></td> |
|
45 <td></td> |
|
46 <td></td> |
|
47 </tr> |
|
48 <tr> |
|
49 <td></td> |
|
50 <td></td> |
|
51 <td></td> |
|
52 <td></td> |
|
53 </tr> |
|
54 <tr> |
|
55 <td></td> |
|
56 <td></td> |
|
57 <td></td> |
|
58 <td></td> |
|
59 </tr> |
|
60 <tr> |
|
61 <td></td> |
|
62 <td></td> |
|
63 <td></td> |
|
64 <td></td> |
|
65 </tr> |
|
66 </table> |
|
67 |
|
68 <div class="test"> |
|
69 <button>Array vs 2d Array vs Object vs this Object</button> |
|
70 <div class="report"></div> |
|
71 </div> |
|
72 |
|
73 <script> |
|
74 var boardDom = document.getElementById("board"); |
|
75 var ui = {}; |
|
76 ui.set = function(i, j, val) { |
|
77 boardDom.querySelectorAll("tr")[i].querySelectorAll("td")[j].innerHTML = val; |
|
78 } |
|
79 </script> |
|
80 |
|
81 <script> |
|
82 /* var N = 1; */ |
|
83 /* var N = 1000*1000; */ |
|
84 var N = 1000*1000; |
|
85 |
|
86 function arrNew() { |
|
87 return [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; |
|
88 } |
|
89 function arrGet(brd, i, j) { |
|
90 return brd[i*4+j]; |
|
91 } |
|
92 function arrSet(brd, i, j, val) { |
|
93 brd[i*4+j] = val; |
|
94 } |
|
95 function arrPrint(brd) { |
|
96 for (var i = 0; i < 4; i++) { |
|
97 for (var j = 0; j < 4; j++) { |
|
98 ui.set(i, j, brd[i*4+j]); |
|
99 } |
|
100 } |
|
101 } |
|
102 function arrRotLeft(from, to) { |
|
103 for (var i = 0; i < 4; i++) { |
|
104 for (var j = 0; j < 3; j++) { |
|
105 to[i*4+j+1] = from[i*4+j]; |
|
106 } |
|
107 to[i*4] = from[i*4+3]; |
|
108 } |
|
109 } |
|
110 function arrRotLeft_2(from, to) { |
|
111 to[1] = from[0]; to[2] = from[1]; to[3] = from[2]; to[0] = from[3]; |
|
112 to[4+1] = from[4+0]; to[4+2] = from[4+1]; to[4+3] = from[4+2]; to[4+0] = from[4+3]; |
|
113 to[8+1] = from[8+0]; to[8+2] = from[8+1]; to[8+3] = from[8+2]; to[8+0] = from[8+3]; |
|
114 to[12+1] = from[12+0]; to[12+2] = from[12+1]; to[12+3] = from[12+2]; to[12+0] = from[12+3]; |
|
115 } |
|
116 |
|
117 var L = arrNew(); |
|
118 L[2*4+3] = 5; |
|
119 for (var i = 0; i < 4; i++) { |
|
120 arrSet(L, i, 3-i, i+1); |
|
121 } |
|
122 var R = arrNew(); |
|
123 |
|
124 /* Example of plain performance calculation. */ |
|
125 var tsFrom = new Date().getTime(); |
|
126 for (var i = 0; i < N; i++) { |
|
127 arrRotLeft(L, R); |
|
128 arrRotLeft(R, L); |
|
129 } |
|
130 var tsTo = new Date().getTime(); |
|
131 arrPrint(L); |
|
132 console.log("arrRotLeft: %f ms, %d u/s", tsTo-tsFrom, 2*i/(tsTo - tsFrom)*1000); |
|
133 |
|
134 perf("arrRotLeft", function() { |
|
135 arrRotLeft(this.L, this.R); |
|
136 arrRotLeft(this.R, this.L); |
|
137 }, N, {L: L, R: R}); |
|
138 arrPrint(L); |
|
139 |
|
140 perf("arrRotLeft_2", function() { |
|
141 arrRotLeft_2(this.L, this.R); |
|
142 arrRotLeft_2(this.R, this.L); |
|
143 }, N, {L: L, R: R}); |
|
144 arrPrint(L); |
|
145 |
|
146 |
|
147 perf("BoardArr.prototype.copy|new", function() { |
|
148 this.brd = this.brd.copy(); |
|
149 }, N, {brd: new BoardArr()}); |
|
150 perf("BoardArr.prototype.copy|from-to", function() { |
|
151 this.from.copy(this.to); |
|
152 }, N, {from: new BoardArr(), to: new BoardArr()}); |
|
153 |
|
154 |
|
155 perf("BoardArr2d.prototype.copy|new", function() { |
|
156 this.brd = this.brd.copy(); |
|
157 }, N, {brd: new BoardArr2d()}); |
|
158 perf("BoardArr2d.prototype.copy|from-to", function() { |
|
159 this.from.copy(this.to); |
|
160 }, N, {from: new BoardArr2d(), to: new BoardArr2d()}); |
|
161 perf("BoardArr2d.prototype.shiftLeft_unrolled", function() { |
|
162 this.from.shiftLeft_unrolled(this.to); |
|
163 var swap = this.from; this.from = this.to, this.to = swap; |
|
164 }, N, {from: new BoardArr2d(), to: new BoardArr2d()}); |
|
165 perf("BoardArr2d.prototype.shiftLeft_mostly_unrolled", function() { |
|
166 this.from.shiftLeft_mostly_unrolled(this.to); |
|
167 var swap = this.from; this.from = this.to, this.to = swap; |
|
168 }, N, {from: new BoardArr2d(), to: new BoardArr2d()}); |
|
169 |
|
170 function arr2New() { |
|
171 return [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]; |
|
172 } |
|
173 function arr2Get(brd, i, j) { |
|
174 return brd[i][j]; |
|
175 } |
|
176 function arr2Set(brd, i, j, val) { |
|
177 brd[i][j] = val; |
|
178 } |
|
179 function arr2Print(brd) { |
|
180 for (var i = 0; i < 4; i++) { |
|
181 for (var j = 0; j < 4; j++) { |
|
182 ui.set(i, j, brd[i][j]); |
|
183 } |
|
184 } |
|
185 } |
|
186 function arr2RotLeft(from, to) { |
|
187 for (var i = 0; i < 4; i++) { |
|
188 for (var j = 0; j < 3; j++) { |
|
189 to[i][j+1] = from[i][j]; |
|
190 } |
|
191 to[i][0] = from[i][3]; |
|
192 } |
|
193 } |
|
194 function arr2RotLeft_2(from, to) { |
|
195 to[0][1] = from[0][0]; to[0][2] = from[0][1]; to[0][3] = from[0][2]; to[0][0] = from[0][3]; |
|
196 to[1][1] = from[1][0]; to[1][2] = from[1][1]; to[1][3] = from[1][2]; to[1][0] = from[1][3]; |
|
197 to[2][1] = from[2][0]; to[2][2] = from[2][1]; to[2][3] = from[2][2]; to[2][0] = from[2][3]; |
|
198 to[3][1] = from[3][0]; to[3][2] = from[3][1]; to[3][3] = from[3][2]; to[3][0] = from[3][3]; |
|
199 } |
|
200 function arr2ShiftRight(from, to) { |
|
201 for (var i = 0; i < 4; i++) { |
|
202 if (from[i][2] == from[i][3]) { |
|
203 to[i][3] = from[i][3] + 1; |
|
204 if (from[i][0] == from[i][1]) { |
|
205 to[i][2] = from[i][1] + 1; |
|
206 to[i][1] = 0; |
|
207 } else { |
|
208 to[i][2] = from[i][1]; |
|
209 to[i][1] = from[i][0]; |
|
210 } |
|
211 to[i][0] = 0; |
|
212 } else { |
|
213 to[i][3] = from[i][3]; |
|
214 if (from[i][1] == from[i][2]) { |
|
215 to[i][2] = from[i][2] + 1; |
|
216 to[i][1] = from[i][0]; |
|
217 to[i][0] = 0; |
|
218 } else { |
|
219 to[i][2] = from[i][2]; |
|
220 if (from[i][0] == from[i][1]) { |
|
221 to[i][1] = from[i][1] + 1; |
|
222 to[i][0] = 0; |
|
223 } else { |
|
224 to[i][1] = from[i][1]; |
|
225 to[i][0] = from[i][0]; |
|
226 } |
|
227 } |
|
228 } |
|
229 } |
|
230 } |
|
231 function arr2ShiftLeft(from, to) { |
|
232 for (var i = 3; i >= 0; i--) { |
|
233 if (from[i][0] == from[i][1]) { |
|
234 to[i][0] = from[i][0] + 1; |
|
235 if (from[i][2] == from[i][3]) { |
|
236 to[i][1] = from[i][2] + 1; |
|
237 to[i][2] = 0; |
|
238 } else { |
|
239 to[i][1] = from[i][2]; |
|
240 to[i][2] = from[i][3]; |
|
241 } |
|
242 to[i][3] = 0; |
|
243 } else { |
|
244 to[i][0] = from[i][0]; |
|
245 if (from[i][1] == from[i][2]) { |
|
246 to[i][1] = from[i][1] + 1; |
|
247 to[i][2] = from[i][3]; |
|
248 to[i][3] = 0; |
|
249 } else { |
|
250 to[i][1] = from[i][1]; |
|
251 if (from[i][2] == from[i][3]) { |
|
252 to[i][2] = from[i][2] + 1; |
|
253 to[i][3] = 0; |
|
254 } else { |
|
255 to[i][2] = from[i][2]; |
|
256 to[i][3] = from[i][3]; |
|
257 } |
|
258 } |
|
259 } |
|
260 } |
|
261 } |
|
262 function arr2ShiftUp(from, to) { |
|
263 for (var j = 3; j >= 0; j--) { |
|
264 if (from[0][j] == from[1][j]) { |
|
265 to[0][j] = from[0][j] + 1; |
|
266 if (from[2][j] == from[3][j]) { |
|
267 to[1][j] = from[2][j] + 1; |
|
268 to[2][j] = 0; |
|
269 } else { |
|
270 to[1][j] = from[2][j]; |
|
271 to[2][j] = from[3][j]; |
|
272 } |
|
273 to[3][j] = 0; |
|
274 } else { |
|
275 to[0][j] = from[0][j]; |
|
276 if (from[1][j] == from[2][j]) { |
|
277 to[1][j] = from[1][j] + 1; |
|
278 to[2][j] = from[3][j]; |
|
279 to[3][j] = 0; |
|
280 } else { |
|
281 to[1][j] = from[1][j]; |
|
282 if (from[2][j] == from[3][j]) { |
|
283 to[2][j] = from[2][j] + 1; |
|
284 to[3][j] = 0; |
|
285 } else { |
|
286 to[2][j] = from[2][j]; |
|
287 to[3][j] = from[3][j]; |
|
288 } |
|
289 } |
|
290 } |
|
291 } |
|
292 } |
|
293 function arr2ShiftDown(from, to) { |
|
294 for (var j = 0; j < 4; j++) { |
|
295 if (from[2][j] == from[3][j]) { |
|
296 to[3][j] = from[3][j] + 1; |
|
297 if (from[0][j] == from[1][j]) { |
|
298 to[2][j] = from[1][j] + 1; |
|
299 to[1][j] = 0; |
|
300 } else { |
|
301 to[2][j] = from[1][j]; |
|
302 to[1][j] = from[0][j]; |
|
303 } |
|
304 to[0][j] = 0; |
|
305 } else { |
|
306 to[3][j] = from[3][j]; |
|
307 if (from[1][j] == from[2][j]) { |
|
308 to[2][j] = from[2][j] + 1; |
|
309 to[1][j] = from[0][j]; |
|
310 to[0][j] = 0; |
|
311 } else { |
|
312 to[2][j] = from[2][j]; |
|
313 if (from[0][j] == from[1][j]) { |
|
314 to[1][j] = from[1][j] + 1; |
|
315 to[0][j] = 0; |
|
316 } else { |
|
317 to[1][j] = from[1][j]; |
|
318 to[0][j] = from[0][j]; |
|
319 } |
|
320 } |
|
321 } |
|
322 } |
|
323 } |
|
324 var L = arr2New(); |
|
325 L[2][3] = 5; |
|
326 for (var i = 0; i < 4; i++) { |
|
327 arr2Set(L, i, 3-i, i+1); |
|
328 } |
|
329 |
|
330 var R = arr2New(); |
|
331 var tsFrom = new Date().getTime(); |
|
332 for (var i = 0; i < N; i++) { |
|
333 arr2RotLeft(L, R); |
|
334 arr2RotLeft(R, L); |
|
335 } |
|
336 var tsTo = new Date().getTime(); |
|
337 /* arr2Print(L); */ |
|
338 console.log("arr2RotLeft: %f ms, %d u/s", tsTo-tsFrom, 2*i/(tsTo - tsFrom)*1000); |
|
339 |
|
340 var tsFrom = new Date().getTime(); |
|
341 for (var i = 0; i < N; i++) { |
|
342 arr2RotLeft_2(L, R); |
|
343 arr2RotLeft_2(R, L); |
|
344 } |
|
345 var tsTo = new Date().getTime(); |
|
346 /* arr2Print(L); */ |
|
347 console.log("arr2RotLeft_2: %f ms, %d u/s", tsTo-tsFrom, 2*i/(tsTo - tsFrom)*1000); |
|
348 |
|
349 |
|
350 var objMap = [["aa", "ab", "ac", "ad"], ["ba", "bb", "bc", "bd"], ["ca", "cb", "cc", "cd"], ["da", "db", "dc", "dd"]]; |
|
351 function objNew() { |
|
352 return { aa: 0, ab: 0, ac: 0, ad: 0, |
|
353 ba: 0, bb: 0, bc: 0, bd: 0, |
|
354 ca: 0, cb: 0, cc: 0, cd: 0, |
|
355 da: 0, db: 0, dc: 0, dd: 0 }; |
|
356 } |
|
357 function objGet(brd, i, j) { |
|
358 return brd[objMap[i][j]]; |
|
359 } |
|
360 function objSet(brd, i, j, val) { |
|
361 brd[objMap[i][j]] = val; |
|
362 } |
|
363 function objPrint(brd) { |
|
364 ui.set(0, 0, brd.aa); ui.set(0, 1, brd.ab); ui.set(0, 2, brd.ac); ui.set(0, 3, brd.ad); |
|
365 ui.set(1, 0, brd.ba); ui.set(1, 1, brd.bb); ui.set(1, 2, brd.bc); ui.set(1, 3, brd.bd); |
|
366 ui.set(2, 0, brd.ca); ui.set(2, 1, brd.cb); ui.set(2, 2, brd.cc); ui.set(2, 3, brd.cd); |
|
367 ui.set(3, 0, brd.da); ui.set(3, 1, brd.db); ui.set(3, 2, brd.dc); ui.set(3, 3, brd.dd); |
|
368 } |
|
369 function objRotLeft(from, to) { |
|
370 to.ab = from.aa; to.ac = from.ab; to.ad = from.ac; to.aa = from.ad; |
|
371 to.bb = from.ba; to.bc = from.bb; to.bd = from.bc; to.ba = from.bd; |
|
372 to.cb = from.ca; to.cc = from.cb; to.cd = from.cc; to.ca = from.cd; |
|
373 to.db = from.da; to.dc = from.db; to.dd = from.dc; to.da = from.dd; |
|
374 } |
|
375 function objRotLeft_2(from, to) { |
|
376 to["ab"] = from["aa"]; to["ac"] = from["ab"]; to["ad"] = from["ac"]; to["aa"] = from["ad"]; |
|
377 to["bb"] = from["ba"]; to["bc"] = from["bb"]; to["bd"] = from["bc"]; to["ba"] = from["bd"]; |
|
378 to["cb"] = from["ca"]; to["cc"] = from["cb"]; to["cd"] = from["cc"]; to["ca"] = from["cd"]; |
|
379 to["db"] = from["da"]; to["dc"] = from["db"]; to["dd"] = from["dc"]; to["da"] = from["dd"]; |
|
380 } |
|
381 var L = objNew(); |
|
382 L.cd = 5; |
|
383 for (var i = 0; i < 4; i++) { |
|
384 objSet(L, i, 3-i, i+1); |
|
385 } |
|
386 |
|
387 var R = objNew(); |
|
388 var tsFrom = new Date().getTime(); |
|
389 for (var i = 0; i < N; i++) { |
|
390 objRotLeft(L, R); |
|
391 objRotLeft(R, L); |
|
392 } |
|
393 var tsTo = new Date().getTime(); |
|
394 objPrint(L); |
|
395 console.log("objRotLeft: %f ms, %d u/s", tsTo-tsFrom, 2*i/(tsTo - tsFrom)*1000); |
|
396 |
|
397 var tsFrom = new Date().getTime(); |
|
398 for (var i = 0; i < N; i++) { |
|
399 objRotLeft_2(L, R); |
|
400 objRotLeft_2(R, L); |
|
401 } |
|
402 var tsTo = new Date().getTime(); |
|
403 objPrint(L); |
|
404 console.log("objRotLeft_2: %f ms, %d u/s", tsTo-tsFrom, 2*i/(tsTo - tsFrom)*1000); |
|
405 </script> |
|
406 |
|
407 <script> |
|
408 /* console.log(Array.prototype.map.call(document.querySelectorAll("button"), function(x){return x;})); */ |
|
409 Array.prototype.forEach.call(document.querySelectorAll("button"), function(btn) { |
|
410 console.log(btn) |
|
411 }); |
|
412 </script> |
|
413 </body> |
|
414 </html> |