diff options
Diffstat (limited to 'tools/perf/perf_tools/smoothness_metrics.js')
-rw-r--r-- | tools/perf/perf_tools/smoothness_metrics.js | 161 |
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; +})(); |