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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « benchmarks/spinning-balls/splay-tree.js ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: benchmarks/spinning-balls/v.js
diff --git a/benchmarks/spinning-balls/v.js b/benchmarks/spinning-balls/v.js
new file mode 100644
index 0000000000000000000000000000000000000000..87366d939303312af2fc67a38779940a45feb66e
--- /dev/null
+++ b/benchmarks/spinning-balls/v.js
@@ -0,0 +1,387 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+/**
+ * This function provides requestAnimationFrame in a cross browser way.
+ * http://paulirish.com/2011/requestanimationframe-for-smart-animating/
+ */
+if ( !window.requestAnimationFrame ) {
+ window.requestAnimationFrame = ( function() {
+ return window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ window.msRequestAnimationFrame ||
+ function(callback, element) {
+ window.setTimeout( callback, 1000 / 60 );
+ };
+ } )();
+}
+
+var kNPoints = 8000;
+var kNModifications = 20;
+var kNVisiblePoints = 200;
+var kDecaySpeed = 20;
+
+var kPointRadius = 4;
+var kInitialLifeForce = 100;
+
+var livePoints = void 0;
+var dyingPoints = void 0;
+var scene = void 0;
+var renderingStartTime = void 0;
+var scene = void 0;
+var pausePlot = void 0;
+var splayTree = void 0;
+
+
+function Point(x, y, z, payload) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+
+ this.next = null;
+ this.prev = null;
+ this.payload = payload;
+ this.lifeForce = kInitialLifeForce;
+}
+
+
+Point.prototype.color = function () {
+ return "rgba(0, 0, 0, " + (this.lifeForce / kInitialLifeForce) + ")";
+};
+
+
+Point.prototype.decay = function () {
+ this.lifeForce -= kDecaySpeed;
+ return this.lifeForce <= 0;
+};
+
+
+function PointsList() {
+ this.head = null;
+ this.count = 0;
+}
+
+
+PointsList.prototype.add = function (point) {
+ if (this.head !== null) this.head.prev = point;
+ point.next = this.head;
+ this.head = point;
+ this.count++;
+}
+
+
+PointsList.prototype.remove = function (point) {
+ if (point.next !== null) {
+ point.next.prev = point.prev;
+ }
+ if (point.prev !== null) {
+ point.prev.next = point.next;
+ } else {
+ this.head = point.next;
+ }
+ this.count--;
+}
+
+
+function GeneratePayloadTree(depth, tag) {
+ if (depth == 0) {
+ return {
+ array : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
+ string : 'String for key ' + tag + ' in leaf node'
+ };
+ } else {
+ return {
+ left: GeneratePayloadTree(depth - 1, tag),
+ right: GeneratePayloadTree(depth - 1, tag)
+ };
+ }
+}
+
+
+// To make the benchmark results predictable, we replace Math.random
+// with a 100% deterministic alternative.
+Math.random = (function() {
+ var seed = 49734321;
+ return function() {
+ // Robert Jenkins' 32 bit integer hash function.
+ seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff;
+ seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff;
+ seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff;
+ seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff;
+ seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff;
+ seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff;
+ return (seed & 0xfffffff) / 0x10000000;
+ };
+})();
+
+
+function GenerateKey() {
+ // The benchmark framework guarantees that Math.random is
+ // deterministic; see base.js.
+ return Math.random();
+}
+
+function CreateNewPoint() {
+ // Insert new node with a unique key.
+ var key;
+ do { key = GenerateKey(); } while (splayTree.find(key) != null);
+
+ var point = new Point(Math.random() * 40 - 20,
+ Math.random() * 40 - 20,
+ Math.random() * 40 - 20,
+ GeneratePayloadTree(5, "" + key));
+
+ livePoints.add(point);
+
+ splayTree.insert(key, point);
+ return key;
+}
+
+function ModifyPointsSet() {
+ if (livePoints.count < kNPoints) {
+ for (var i = 0; i < kNModifications; i++) {
+ CreateNewPoint();
+ }
+ } else if (kNModifications === 20) {
+ kNModifications = 80;
+ kDecay = 30;
+ }
+
+ for (var i = 0; i < kNModifications; i++) {
+ var key = CreateNewPoint();
+ var greatest = splayTree.findGreatestLessThan(key);
+ if (greatest == null) {
+ var point = splayTree.remove(key).value;
+ } else {
+ var point = splayTree.remove(greatest.key).value;
+ }
+ livePoints.remove(point);
+ point.payload = null;
+ dyingPoints.add(point);
+ }
+}
+
+
+function PausePlot(width, height, size) {
+ var canvas = document.createElement("canvas");
+ canvas.width = this.width = width;
+ canvas.height = this.height = height;
+ document.body.appendChild(canvas);
+
+ this.ctx = canvas.getContext('2d');
+
+ this.maxPause = 0;
+ this.size = size;
+
+ // Initialize cyclic buffer for pauses.
+ this.pauses = new Array(this.size);
+ this.start = this.size;
+ this.idx = 0;
+}
+
+
+PausePlot.prototype.addPause = function (p) {
+ if (this.idx === this.size) {
+ this.idx = 0;
+ }
+
+ if (this.idx === this.start) {
+ this.start++;
+ }
+
+ if (this.start === this.size) {
+ this.start = 0;
+ }
+
+ this.pauses[this.idx++] = p;
+};
+
+
+PausePlot.prototype.iteratePauses = function (f) {
+ if (this.start < this.idx) {
+ for (var i = this.start; i < this.idx; i++) {
+ f.call(this, i - this.start, this.pauses[i]);
+ }
+ } else {
+ for (var i = this.start; i < this.size; i++) {
+ f.call(this, i - this.start, this.pauses[i]);
+ }
+
+ var offs = this.size - this.start;
+ for (var i = 0; i < this.idx; i++) {
+ f.call(this, i + offs, this.pauses[i]);
+ }
+ }
+};
+
+
+PausePlot.prototype.draw = function () {
+ var first = null;
+ this.iteratePauses(function (i, v) {
+ if (first === null) {
+ first = v;
+ }
+ this.maxPause = Math.max(v, this.maxPause);
+ });
+
+ var dx = this.width / this.size;
+ var dy = this.height / this.maxPause;
+
+ this.ctx.save();
+ this.ctx.clearRect(0, 0, 480, 240);
+ this.ctx.beginPath();
+ this.ctx.moveTo(1, dy * this.pauses[this.start]);
+ var p = first;
+ this.iteratePauses(function (i, v) {
+ var delta = v - p;
+ var x = 1 + dx * i;
+ var y = dy * v;
+ this.ctx.lineTo(x, y);
+ if (delta > 2 * (p / 3)) {
+ this.ctx.font = "bold 12px sans-serif";
+ this.ctx.textBaseline = "bottom";
+ this.ctx.fillText(v + "ms", x + 2, y);
+ }
+ p = v;
+ });
+ this.ctx.strokeStyle = "black";
+ this.ctx.stroke();
+ this.ctx.restore();
+}
+
+
+function Scene(width, height) {
+ var canvas = document.createElement("canvas");
+ canvas.width = width;
+ canvas.height = height;
+ document.body.appendChild(canvas);
+
+ this.ctx = canvas.getContext('2d');
+ this.width = canvas.width;
+ this.height = canvas.height;
+
+ // Projection configuration.
+ this.x0 = canvas.width / 2;
+ this.y0 = canvas.height / 2;
+ this.z0 = 100;
+ this.f = 1000; // Focal length.
+
+ // Camera is rotating around y-axis.
+ this.angle = 0;
+}
+
+
+Scene.prototype.drawPoint = function (x, y, z, color) {
+ // Rotate the camera around y-axis.
+ var rx = x * Math.cos(this.angle) - z * Math.sin(this.angle);
+ var ry = y;
+ var rz = x * Math.sin(this.angle) + z * Math.cos(this.angle);
+
+ // Perform perspective projection.
+ var px = (this.f * rx) / (rz - this.z0) + this.x0;
+ var py = (this.f * ry) / (rz - this.z0) + this.y0;
+
+ this.ctx.save();
+ this.ctx.fillStyle = color
+ this.ctx.beginPath();
+ this.ctx.arc(px, py, kPointRadius, 0, 2 * Math.PI, true);
+ this.ctx.fill();
+ this.ctx.restore();
+};
+
+
+Scene.prototype.drawDyingPoints = function () {
+ var point_next = null;
+ for (var point = dyingPoints.head; point !== null; point = point_next) {
+ // Rotate the scene around y-axis.
+ scene.drawPoint(point.x, point.y, point.z, point.color());
+
+ point_next = point.next;
+
+ // Decay the current point and remove it from the list
+ // if it's life-force ran out.
+ if (point.decay()) {
+ dyingPoints.remove(point);
+ }
+ }
+};
+
+
+Scene.prototype.draw = function () {
+ this.ctx.save();
+ this.ctx.clearRect(0, 0, this.width, this.height);
+ this.drawDyingPoints();
+ this.ctx.restore();
+
+ this.angle += Math.PI / 90.0;
+};
+
+
+function render() {
+ if (typeof renderingStartTime === 'undefined') {
+ renderingStartTime = Date.now();
+ }
+
+ ModifyPointsSet();
+
+ scene.draw();
+
+ var renderingEndTime = Date.now();
+ var pause = renderingEndTime - renderingStartTime;
+ pausePlot.addPause(pause);
+ renderingStartTime = renderingEndTime;
+
+ pausePlot.draw();
+
+ div.innerHTML =
+ livePoints.count + "/" + dyingPoints.count + " " +
+ pause + "(max = " + pausePlot.maxPause + ") ms" ;
+
+ // Schedule next frame.
+ requestAnimationFrame(render);
+}
+
+
+function init() {
+ livePoints = new PointsList;
+ dyingPoints = new PointsList;
+
+ splayTree = new SplayTree();
+
+ scene = new Scene(640, 480);
+
+ div = document.createElement("div");
+ document.body.appendChild(div);
+
+ pausePlot = new PausePlot(480, 240, 160);
+}
+
+
+init();
+render();
« 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