summaryrefslogtreecommitdiffstats
path: root/tools/perf/perf_tools/smoothness_metrics.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/perf_tools/smoothness_metrics.js')
-rw-r--r--tools/perf/perf_tools/smoothness_metrics.js161
1 files changed, 161 insertions, 0 deletions
diff --git a/tools/perf/perf_tools/smoothness_metrics.js b/tools/perf/perf_tools/smoothness_metrics.js
new file mode 100644
index 0000000..22336fe
--- /dev/null
+++ b/tools/perf/perf_tools/smoothness_metrics.js
@@ -0,0 +1,161 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+/**
+ * @fileoverview This file provides the RenderingStats object, used
+ * to characterize rendering smoothness.
+ */
+(function() {
+ var getTimeMs = (function() {
+ if (window.performance)
+ return (performance.now ||
+ performance.mozNow ||
+ performance.msNow ||
+ performance.oNow ||
+ performance.webkitNow).bind(window.performance);
+ else
+ return function() { return new Date().getTime(); };
+ })();
+
+ var requestAnimationFrame = (function() {
+ return window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ window.msRequestAnimationFrame ||
+ function(callback) {
+ window.setTimeout(callback, 1000 / 60);
+ };
+ })().bind(window);
+
+ /**
+ * Tracks rendering performance using the gpuBenchmarking.renderingStats API.
+ * @constructor
+ */
+ function GpuBenchmarkingRenderingStats() {
+ }
+
+ GpuBenchmarkingRenderingStats.prototype.start = function() {
+ this.startTime_ = getTimeMs();
+ this.initialStats_ = this.getRenderingStats_();
+ }
+
+ GpuBenchmarkingRenderingStats.prototype.stop = function() {
+ this.stopTime_ = getTimeMs();
+ this.finalStats_ = this.getRenderingStats_();
+ }
+
+ GpuBenchmarkingRenderingStats.prototype.getStartValues = function() {
+ if (!this.initialStats_)
+ throw new Error('Start not called.');
+
+ if (!this.finalStats_)
+ throw new Error('Stop was not called.');
+
+ return this.initialStats_;
+ }
+
+ GpuBenchmarkingRenderingStats.prototype.getEndValues = function() {
+ if (!this.initialStats_)
+ throw new Error('Start not called.');
+
+ if (!this.finalStats_)
+ throw new Error('Stop was not called.');
+
+ return this.finalStats_;
+ }
+
+ GpuBenchmarkingRenderingStats.prototype.getDeltas = function() {
+ if (!this.initialStats_)
+ throw new Error('Start not called.');
+
+ if (!this.finalStats_)
+ throw new Error('Stop was not called.');
+
+ var stats = {}
+ for (var key in this.finalStats_)
+ stats[key] = this.finalStats_[key] - this.initialStats_[key];
+ return stats;
+ };
+
+ GpuBenchmarkingRenderingStats.prototype.getRenderingStats_ = function() {
+ var stats = chrome.gpuBenchmarking.renderingStats();
+ stats.totalTimeInSeconds = getTimeMs() / 1000;
+ return stats;
+ };
+
+ /**
+ * Tracks rendering performance using requestAnimationFrame.
+ * @constructor
+ */
+ function RafRenderingStats() {
+ this.recording_ = false;
+ this.frameTimes_ = [];
+ }
+
+ RafRenderingStats.prototype.start = function() {
+ if (this.recording_)
+ throw new Error('Already started.');
+ this.recording_ = true;
+ requestAnimationFrame(this.recordFrameTime_.bind(this));
+ }
+
+ RafRenderingStats.prototype.stop = function() {
+ this.recording_ = false;
+ }
+
+ RafRenderingStats.prototype.getStartValues = function() {
+ var results = {};
+ results.numAnimationFrames = 0;
+ results.numFramesSentToScreen = 0;
+ results.droppedFrameCount = 0;
+ return results;
+ }
+
+ RafRenderingStats.prototype.getEndValues = function() {
+ var results = {};
+ results.numAnimationFrames = this.frameTimes_.length - 1;
+ results.numFramesSentToScreen = results.numAnimationFrames;
+ results.droppedFrameCount = this.getDroppedFrameCount_(this.frameTimes_);
+ return results;
+ }
+
+ RafRenderingStats.prototype.getDeltas = function() {
+ var endValues = this.getEndValues();
+ endValues.totalTimeInSeconds = (
+ this.frameTimes_[this.frameTimes_.length - 1] -
+ this.frameTimes_[0]) / 1000;
+ return endValues;
+ };
+
+ RafRenderingStats.prototype.recordFrameTime_ = function(timestamp) {
+ if (!this.recording_)
+ return;
+
+ this.frameTimes_.push(timestamp);
+ requestAnimationFrame(this.recordFrameTime_.bind(this));
+ };
+
+ RafRenderingStats.prototype.getDroppedFrameCount_ = function(frameTimes) {
+ var droppedFrameCount = 0;
+ for (var i = 1; i < frameTimes.length; i++) {
+ var frameTime = frameTimes[i] - frameTimes[i-1];
+ if (frameTime > 1000 / 55)
+ droppedFrameCount++;
+ }
+ return droppedFrameCount;
+ };
+
+ function RenderingStats() {
+ if (window.chrome && chrome.gpuBenchmarking &&
+ chrome.gpuBenchmarking.renderingStats) {
+ return new GpuBenchmarkingRenderingStats();
+ }
+ return new RafRenderingStats();
+ }
+
+ window.__RenderingStats = RenderingStats;
+})();