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

Side by Side Diff: benchmarks/spinning-balls/v.js

Issue 8139001: GC pauses visualization tool. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « benchmarks/spinning-balls/splay-tree.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28
29 /**
30 * This function provides requestAnimationFrame in a cross browser way.
31 * http://paulirish.com/2011/requestanimationframe-for-smart-animating/
32 */
33 if ( !window.requestAnimationFrame ) {
34 window.requestAnimationFrame = ( function() {
35 return window.webkitRequestAnimationFrame ||
36 window.mozRequestAnimationFrame ||
37 window.oRequestAnimationFrame ||
38 window.msRequestAnimationFrame ||
39 function(callback, element) {
40 window.setTimeout( callback, 1000 / 60 );
41 };
42 } )();
43 }
44
45 var kNPoints = 8000;
46 var kNModifications = 20;
47 var kNVisiblePoints = 200;
48 var kDecaySpeed = 20;
49
50 var kPointRadius = 4;
51 var kInitialLifeForce = 100;
52
53 var livePoints = void 0;
54 var dyingPoints = void 0;
55 var scene = void 0;
56 var renderingStartTime = void 0;
57 var scene = void 0;
58 var pausePlot = void 0;
59 var splayTree = void 0;
60
61
62 function Point(x, y, z, payload) {
63 this.x = x;
64 this.y = y;
65 this.z = z;
66
67 this.next = null;
68 this.prev = null;
69 this.payload = payload;
70 this.lifeForce = kInitialLifeForce;
71 }
72
73
74 Point.prototype.color = function () {
75 return "rgba(0, 0, 0, " + (this.lifeForce / kInitialLifeForce) + ")";
76 };
77
78
79 Point.prototype.decay = function () {
80 this.lifeForce -= kDecaySpeed;
81 return this.lifeForce <= 0;
82 };
83
84
85 function PointsList() {
86 this.head = null;
87 this.count = 0;
88 }
89
90
91 PointsList.prototype.add = function (point) {
92 if (this.head !== null) this.head.prev = point;
93 point.next = this.head;
94 this.head = point;
95 this.count++;
96 }
97
98
99 PointsList.prototype.remove = function (point) {
100 if (point.next !== null) {
101 point.next.prev = point.prev;
102 }
103 if (point.prev !== null) {
104 point.prev.next = point.next;
105 } else {
106 this.head = point.next;
107 }
108 this.count--;
109 }
110
111
112 function GeneratePayloadTree(depth, tag) {
113 if (depth == 0) {
114 return {
115 array : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
116 string : 'String for key ' + tag + ' in leaf node'
117 };
118 } else {
119 return {
120 left: GeneratePayloadTree(depth - 1, tag),
121 right: GeneratePayloadTree(depth - 1, tag)
122 };
123 }
124 }
125
126
127 // To make the benchmark results predictable, we replace Math.random
128 // with a 100% deterministic alternative.
129 Math.random = (function() {
130 var seed = 49734321;
131 return function() {
132 // Robert Jenkins' 32 bit integer hash function.
133 seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff;
134 seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff;
135 seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff;
136 seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff;
137 seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff;
138 seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff;
139 return (seed & 0xfffffff) / 0x10000000;
140 };
141 })();
142
143
144 function GenerateKey() {
145 // The benchmark framework guarantees that Math.random is
146 // deterministic; see base.js.
147 return Math.random();
148 }
149
150 function CreateNewPoint() {
151 // Insert new node with a unique key.
152 var key;
153 do { key = GenerateKey(); } while (splayTree.find(key) != null);
154
155 var point = new Point(Math.random() * 40 - 20,
156 Math.random() * 40 - 20,
157 Math.random() * 40 - 20,
158 GeneratePayloadTree(5, "" + key));
159
160 livePoints.add(point);
161
162 splayTree.insert(key, point);
163 return key;
164 }
165
166 function ModifyPointsSet() {
167 if (livePoints.count < kNPoints) {
168 for (var i = 0; i < kNModifications; i++) {
169 CreateNewPoint();
170 }
171 } else if (kNModifications === 20) {
172 kNModifications = 80;
173 kDecay = 30;
174 }
175
176 for (var i = 0; i < kNModifications; i++) {
177 var key = CreateNewPoint();
178 var greatest = splayTree.findGreatestLessThan(key);
179 if (greatest == null) {
180 var point = splayTree.remove(key).value;
181 } else {
182 var point = splayTree.remove(greatest.key).value;
183 }
184 livePoints.remove(point);
185 point.payload = null;
186 dyingPoints.add(point);
187 }
188 }
189
190
191 function PausePlot(width, height, size) {
192 var canvas = document.createElement("canvas");
193 canvas.width = this.width = width;
194 canvas.height = this.height = height;
195 document.body.appendChild(canvas);
196
197 this.ctx = canvas.getContext('2d');
198
199 this.maxPause = 0;
200 this.size = size;
201
202 // Initialize cyclic buffer for pauses.
203 this.pauses = new Array(this.size);
204 this.start = this.size;
205 this.idx = 0;
206 }
207
208
209 PausePlot.prototype.addPause = function (p) {
210 if (this.idx === this.size) {
211 this.idx = 0;
212 }
213
214 if (this.idx === this.start) {
215 this.start++;
216 }
217
218 if (this.start === this.size) {
219 this.start = 0;
220 }
221
222 this.pauses[this.idx++] = p;
223 };
224
225
226 PausePlot.prototype.iteratePauses = function (f) {
227 if (this.start < this.idx) {
228 for (var i = this.start; i < this.idx; i++) {
229 f.call(this, i - this.start, this.pauses[i]);
230 }
231 } else {
232 for (var i = this.start; i < this.size; i++) {
233 f.call(this, i - this.start, this.pauses[i]);
234 }
235
236 var offs = this.size - this.start;
237 for (var i = 0; i < this.idx; i++) {
238 f.call(this, i + offs, this.pauses[i]);
239 }
240 }
241 };
242
243
244 PausePlot.prototype.draw = function () {
245 var first = null;
246 this.iteratePauses(function (i, v) {
247 if (first === null) {
248 first = v;
249 }
250 this.maxPause = Math.max(v, this.maxPause);
251 });
252
253 var dx = this.width / this.size;
254 var dy = this.height / this.maxPause;
255
256 this.ctx.save();
257 this.ctx.clearRect(0, 0, 480, 240);
258 this.ctx.beginPath();
259 this.ctx.moveTo(1, dy * this.pauses[this.start]);
260 var p = first;
261 this.iteratePauses(function (i, v) {
262 var delta = v - p;
263 var x = 1 + dx * i;
264 var y = dy * v;
265 this.ctx.lineTo(x, y);
266 if (delta > 2 * (p / 3)) {
267 this.ctx.font = "bold 12px sans-serif";
268 this.ctx.textBaseline = "bottom";
269 this.ctx.fillText(v + "ms", x + 2, y);
270 }
271 p = v;
272 });
273 this.ctx.strokeStyle = "black";
274 this.ctx.stroke();
275 this.ctx.restore();
276 }
277
278
279 function Scene(width, height) {
280 var canvas = document.createElement("canvas");
281 canvas.width = width;
282 canvas.height = height;
283 document.body.appendChild(canvas);
284
285 this.ctx = canvas.getContext('2d');
286 this.width = canvas.width;
287 this.height = canvas.height;
288
289 // Projection configuration.
290 this.x0 = canvas.width / 2;
291 this.y0 = canvas.height / 2;
292 this.z0 = 100;
293 this.f = 1000; // Focal length.
294
295 // Camera is rotating around y-axis.
296 this.angle = 0;
297 }
298
299
300 Scene.prototype.drawPoint = function (x, y, z, color) {
301 // Rotate the camera around y-axis.
302 var rx = x * Math.cos(this.angle) - z * Math.sin(this.angle);
303 var ry = y;
304 var rz = x * Math.sin(this.angle) + z * Math.cos(this.angle);
305
306 // Perform perspective projection.
307 var px = (this.f * rx) / (rz - this.z0) + this.x0;
308 var py = (this.f * ry) / (rz - this.z0) + this.y0;
309
310 this.ctx.save();
311 this.ctx.fillStyle = color
312 this.ctx.beginPath();
313 this.ctx.arc(px, py, kPointRadius, 0, 2 * Math.PI, true);
314 this.ctx.fill();
315 this.ctx.restore();
316 };
317
318
319 Scene.prototype.drawDyingPoints = function () {
320 var point_next = null;
321 for (var point = dyingPoints.head; point !== null; point = point_next) {
322 // Rotate the scene around y-axis.
323 scene.drawPoint(point.x, point.y, point.z, point.color());
324
325 point_next = point.next;
326
327 // Decay the current point and remove it from the list
328 // if it's life-force ran out.
329 if (point.decay()) {
330 dyingPoints.remove(point);
331 }
332 }
333 };
334
335
336 Scene.prototype.draw = function () {
337 this.ctx.save();
338 this.ctx.clearRect(0, 0, this.width, this.height);
339 this.drawDyingPoints();
340 this.ctx.restore();
341
342 this.angle += Math.PI / 90.0;
343 };
344
345
346 function render() {
347 if (typeof renderingStartTime === 'undefined') {
348 renderingStartTime = Date.now();
349 }
350
351 ModifyPointsSet();
352
353 scene.draw();
354
355 var renderingEndTime = Date.now();
356 var pause = renderingEndTime - renderingStartTime;
357 pausePlot.addPause(pause);
358 renderingStartTime = renderingEndTime;
359
360 pausePlot.draw();
361
362 div.innerHTML =
363 livePoints.count + "/" + dyingPoints.count + " " +
364 pause + "(max = " + pausePlot.maxPause + ") ms" ;
365
366 // Schedule next frame.
367 requestAnimationFrame(render);
368 }
369
370
371 function init() {
372 livePoints = new PointsList;
373 dyingPoints = new PointsList;
374
375 splayTree = new SplayTree();
376
377 scene = new Scene(640, 480);
378
379 div = document.createElement("div");
380 document.body.appendChild(div);
381
382 pausePlot = new PausePlot(480, 240, 160);
383 }
384
385
386 init();
387 render();
OLDNEW
« no previous file with comments | « benchmarks/spinning-balls/splay-tree.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698