1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Run benchmark for at least this many milliseconds.
6 var minTotalTimeMs
= 10 * 1000;
7 // Run benchmark at least this many times.
9 // Discard results for this many milliseconds after startup.
10 var warmUpTimeMs
= 1000;
11 var benchmarkStartTime
;
13 var loadingTimesMs
= [];
17 var now
= (function() {
18 if (window
.performance
)
19 return (window
.performance
.now
||
20 window
.performance
.webkitNow
).bind(window
.performance
);
21 return Date
.now
.bind(window
);
24 getImageFormat = function() {
25 if (document
.location
.search
) {
26 return document
.location
.search
.substr(1);
31 prepareImageElement = function() {
32 img
= document
.createElement('img');
33 // Scale the image down to the display size to make sure the entire image is
34 // decoded. If the image is much larger than the display, some browsers might
35 // only decode the visible portion of the image, which would skew the results
37 img
.setAttribute('width', '100%');
38 img
.setAttribute('height', '100%');
39 document
.body
.appendChild(img
);
40 console
.log("Running benchmark for at least " + minTotalTimeMs
+
41 " ms and at least " + minIterations
+ " times.");
42 document
.getElementById('status').innerHTML
= "Benchmark running.";
43 setStatus(getImageFormat().toUpperCase() + " benchmark running.");
44 benchmarkStartTimeMs
= now();
47 setStatus = function(status
) {
48 document
.getElementById('status').innerHTML
= status
;
51 runBenchmark = function() {
52 setStatus("Preparing benchmark.");
53 prepareImageElement();
57 var iteration
= (new Date
).getTime();
59 startLoadingImage = function() {
60 img
.style
.display
= 'none';
61 img
.setAttribute('onload', '');
62 img
.setAttribute('src', '');
63 img
.addEventListener('load', onImageLoaded
);
65 // Setting 'src' and 'display' above causes a repaint. Let it finish before
66 // loading a new image. Ensures loading and painting don't overlap.
67 requestAnimationFrame(function() {
68 loadStartTimeMs
= now();
69 // Use a unique URL for each test iteration to work around image caching.
70 img
.setAttribute('src', 'droids.' + getImageFormat() + '?' + iteration
);
75 var requestAnimationFrame
= (function() {
76 return window
.requestAnimationFrame
||
77 window
.webkitRequestAnimationFrame
||
78 window
.mozRequestAnimationFrame
||
79 window
.oRequestAnimationFrame
||
80 window
.msRequestAnimationFrame
||
82 window
.setTimeout(callback
, 1000 / 60);
86 onImageLoaded = function() {
88 var loadingTimeMs
= nowMs
- loadStartTimeMs
;
89 if (nowMs
- benchmarkStartTimeMs
>= warmUpTimeMs
) {
90 loadingTimesMs
.push(loadingTimeMs
);
92 if (nowMs
- benchmarkStartTimeMs
< minTotalTimeMs
||
93 loadingTimesMs
.length
< minIterations
) {
94 // Repaint happens right after the image is loaded. Make sure painting
95 // is completed before making the image visible. Setting the image to
96 // visible will start decoding. After decoding and painting are completed
97 // we'll start next test iteration.
98 // Double rAF is needed here otherwise the image is barely visible.
99 requestAnimationFrame(function() {
100 img
.style
.display
= '';
101 requestAnimationFrame(startLoadingImage
);
105 console
.log("loadingTimes: " + loadingTimesMs
);
106 setStatus(getImageFormat().toUpperCase() + " benchmark finished: " +
111 averageLoadingTimeMs = function() {
112 if (!loadingTimesMs
.length
)
115 for (var i
= 0; i
< loadingTimesMs
.length
; ++i
) {
116 total
+= loadingTimesMs
[i
];
118 return total
/ loadingTimesMs
.length
;