| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview Perform various "gestures" and calculate average frame rate. | 6 * @fileoverview Perform various "gestures" and calculate average frame rate. |
| 7 * "Gestures" are recorded scrolling behaviors in terms of time (ms) and | 7 * "Gestures" are recorded scrolling behaviors in terms of time (ms) and |
| 8 * absolute positions. | 8 * absolute positions. |
| 9 * | 9 * |
| 10 * How to run a single gesture: | 10 * How to run a single gesture: |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 * ], | 34 * ], |
| 35 */ | 35 */ |
| 36 | 36 |
| 37 var __initialized = true; | 37 var __initialized = true; |
| 38 var __running = false; | 38 var __running = false; |
| 39 var __running_all = false; | 39 var __running_all = false; |
| 40 var __old_title = ""; | 40 var __old_title = ""; |
| 41 var __raf_is_live = false; | 41 var __raf_is_live = false; |
| 42 var __raf; | 42 var __raf; |
| 43 | 43 |
| 44 var __t_start; |
| 44 var __t_last; | 45 var __t_last; |
| 45 var __t_est; | 46 var __t_est; |
| 46 var __t_est_total; | 47 var __t_frame_intervals; |
| 47 var __t_est_squared_total; | |
| 48 var __t_count; | |
| 49 var __t_start; | |
| 50 | 48 |
| 51 var __queued_gesture_functions; | 49 var __queued_gesture_functions; |
| 52 var __results; | 50 var __results; |
| 53 | 51 |
| 54 var __recording = []; | 52 var __recording = []; |
| 55 var __advance_gesture; | 53 var __advance_gesture; |
| 56 | 54 |
| 57 // This flag indicates whether the test page contains an animation loop | 55 // This flag indicates whether the test page contains an animation loop |
| 58 // For more on testing animated pages, see head_animation.js | 56 // For more on testing animated pages, see head_animation.js |
| 59 var __animation = false; | 57 var __animation = false; |
| 60 | 58 |
| 61 var __gesture_library = { | 59 var __gesture_library = { |
| 62 init: [ | 60 init: [ |
| 63 {"time_ms":1, "y":0}, | 61 {"time_ms":1, "y":0}, |
| 64 {"time_ms":5, "y":10} | 62 {"time_ms":5, "y":10} |
| 65 ], | 63 ], |
| 66 stationary: [ | 64 stationary: [ |
| 67 {"time_ms":1, "y":0}, | 65 {"time_ms":1, "y":0}, |
| 68 {"time_ms":5000, "y":0} | 66 {"time_ms":5000, "y":0} |
| 69 ], | 67 ], |
| 68 steady: [ |
| 69 {"time_ms":1, "y":0}, |
| 70 {"time_ms":500, "y":400} |
| 71 ], |
| 70 reading: [ | 72 reading: [ |
| 71 {"time_ms":1, "y":0}, | 73 {"time_ms":1, "y":0}, |
| 72 {"time_ms":842, "y":40}, | 74 {"time_ms":842, "y":40}, |
| 73 {"time_ms":858, "y":67}, | 75 {"time_ms":858, "y":67}, |
| 74 {"time_ms":874, "y":94}, | 76 {"time_ms":874, "y":94}, |
| 75 {"time_ms":890, "y":149}, | 77 {"time_ms":890, "y":149}, |
| 76 {"time_ms":907, "y":203}, | 78 {"time_ms":907, "y":203}, |
| 77 {"time_ms":923, "y":257}, | 79 {"time_ms":923, "y":257}, |
| 78 {"time_ms":939, "y":311}, | 80 {"time_ms":939, "y":311}, |
| 79 {"time_ms":955, "y":393}, | 81 {"time_ms":955, "y":393}, |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 var new_gesture = JSON.parse(JSON.stringify(gesture)); | 175 var new_gesture = JSON.parse(JSON.stringify(gesture)); |
| 174 for (var i = 0; i < new_gesture.length; ++i) { | 176 for (var i = 0; i < new_gesture.length; ++i) { |
| 175 new_gesture[i].time_ms *= stretch_factor; | 177 new_gesture[i].time_ms *= stretch_factor; |
| 176 } | 178 } |
| 177 return new_gesture; | 179 return new_gesture; |
| 178 } | 180 } |
| 179 | 181 |
| 180 // Gesture set to use for testing, initialized with default gesture set. | 182 // Gesture set to use for testing, initialized with default gesture set. |
| 181 // Redefine in test file to use a different set of gestures. | 183 // Redefine in test file to use a different set of gestures. |
| 182 var __gestures = { | 184 var __gestures = { |
| 183 none: __gesture_library["stationary"], | 185 steady: __gesture_library["steady"], |
| 184 steady: __gesture_library["init"], | |
| 185 reading: __gesture_library["reading"], | |
| 186 mouse_wheel: __gesture_library["mouse_wheel"], | |
| 187 mac_fling: __gesture_library["mac_fling"], | |
| 188 }; | 186 }; |
| 189 | 187 |
| 190 function __init_stats() { | 188 function __init_stats() { |
| 191 __t_last = undefined; | 189 __t_last = undefined; |
| 192 __t_est = undefined; | 190 __t_est = undefined; |
| 193 __t_est_total = 0; | 191 __t_frame_intervals = []; |
| 194 __t_est_squared_total = 0; | |
| 195 __t_count = 0; | |
| 196 } | 192 } |
| 197 __init_stats(); | 193 __init_stats(); |
| 198 | 194 |
| 195 var __cur_chrome_interval; |
| 196 function __init_time() { |
| 197 if (chrome.Interval) { |
| 198 __cur_chrome_interval = new chrome.Interval(); |
| 199 __cur_chrome_interval.start(); |
| 200 } |
| 201 } |
| 202 __init_time(); |
| 203 |
| 204 function __get_time() { |
| 205 if (__cur_chrome_interval) |
| 206 return __cur_chrome_interval.microseconds() / 1000; |
| 207 return new Date().getTime(); |
| 208 } |
| 209 |
| 199 function __init_raf() { | 210 function __init_raf() { |
| 200 if ("requestAnimationFrame" in window) | 211 if ("requestAnimationFrame" in window) |
| 201 __raf = requestAnimationFrame; | 212 __raf = requestAnimationFrame; |
| 202 else if ("webkitRequestAnimationFrame" in window) | 213 else if ("webkitRequestAnimationFrame" in window) |
| 203 __raf = webkitRequestAnimationFrame; | 214 __raf = webkitRequestAnimationFrame; |
| 204 else if ("mozRequestAnimationFrame" in window) | 215 else if ("mozRequestAnimationFrame" in window) |
| 205 __raf = mozRequestAnimationFrame; | 216 __raf = mozRequestAnimationFrame; |
| 206 else if ("oRequestAnimationFrame" in window) | 217 else if ("oRequestAnimationFrame" in window) |
| 207 __raf = oRequestAnimationFrame; | 218 __raf = oRequestAnimationFrame; |
| 208 else if ("msRequestAnimationFrame" in window) | 219 else if ("msRequestAnimationFrame" in window) |
| 209 __raf = msRequestAnimationFrame; | 220 __raf = msRequestAnimationFrame; |
| 210 else | 221 else |
| 211 // No raf implementation available, fake it with 16ms timeouts | 222 // No raf implementation available, fake it with 16ms timeouts |
| 212 __raf = function(callback, element) { | 223 __raf = function(callback, element) { |
| 213 setTimeout(callback, 16); | 224 setTimeout(callback, 16); |
| 214 } | 225 }; |
| 215 } | 226 } |
| 216 __init_raf(); | 227 __init_raf(); |
| 217 | 228 |
| 218 function __calc_results() { | 229 function __calc_results() { |
| 219 var M = __t_est_total / __t_count; | 230 var M = 0.0; |
| 220 var X = __t_est_squared_total / __t_count; | 231 var N = __t_frame_intervals.length; |
| 221 var V = X - M * M; | 232 |
| 222 var S = Math.sqrt(V); | 233 for (var i = 0; i < N; i++) |
| 234 M += __t_frame_intervals[i]; |
| 235 M = M / N; |
| 236 |
| 237 var V = 0.0; |
| 238 for (var i = 0; i < N; i++) { |
| 239 var v = __t_frame_intervals[i] - M; |
| 240 V += v * v; |
| 241 } |
| 242 |
| 243 var S = Math.sqrt(V / (N - 1)); |
| 223 | 244 |
| 224 var R = new Object(); | 245 var R = new Object(); |
| 225 R.mean = 1000.0 / M; | 246 R.mean = M; |
| 226 R.sigma = R.mean - 1000.0 / (M + S); | 247 R.sigma = S; |
| 227 return R; | 248 return R; |
| 228 } | 249 } |
| 229 | 250 |
| 230 function __calc_results_total() { | 251 function __calc_results_total() { |
| 231 if (!__results) { | 252 if (!__results) { |
| 232 return; | 253 return {}; |
| 233 } | 254 } |
| 234 var size = __results.gestures.length; | 255 var size = __results.gestures.length; |
| 235 var mean = 0; | 256 var mean = 0; |
| 236 var variance = 0; | 257 var variance = 0; |
| 237 var sigma; | |
| 238 | 258 |
| 239 // Remove any intial caching test(s). | 259 // Remove any intial caching test(s). |
| 240 while (__results.means.length != size) { | 260 while (__results.means.length != size) { |
| 241 __results.means.shift(); | 261 __results.means.shift(); |
| 242 __results.sigmas.shift(); | 262 __results.sigmas.shift(); |
| 243 } | 263 } |
| 244 for (var i = 0; i < size; i++) { | 264 for (var i = 0; i < size; i++) { |
| 245 mean += __results.means[i]; | 265 mean += __results.means[i]; |
| 246 variance += __results.sigmas[i] * __results.sigmas[i]; | 266 variance += __results.sigmas[i] * __results.sigmas[i]; |
| 247 } | 267 } |
| 248 mean /= size; | 268 mean /= size; |
| 249 variance /= size; | 269 variance /= size; |
| 250 sigma = Math.sqrt(variance); | 270 var sigma = Math.sqrt(variance); |
| 251 | 271 |
| 252 var results = new Object(); | 272 var results = new Object(); |
| 253 // GTest expects a comma-separated string for lists. | 273 // GTest expects a comma-separated string for lists. |
| 254 results.gestures = __results.gestures.join(","); | 274 results.gestures = __results.gestures.join(","); |
| 255 results.means = __results.means.join(","); | 275 results.means = __results.means.join(","); |
| 256 results.sigmas = __results.sigmas.join(","); | 276 results.sigmas = __results.sigmas.join(","); |
| 257 results.mean = mean; | 277 results.mean = mean; |
| 258 results.sigma = sigma; | 278 results.sigma = sigma; |
| 259 return results; | 279 return results; |
| 260 } | 280 } |
| 261 | 281 |
| 262 function __update_fps() { | 282 function __record_frame_time() { |
| 263 var t_now = new Date().getTime(); | 283 var t_now = __get_time(); |
| 264 if (window.__t_last) { | 284 if (window.__t_last) { |
| 265 var t_delta = t_now - __t_last; | 285 var t_delta = t_now - __t_last; |
| 266 if (window.__t_est) { | 286 if (window.__t_est) { |
| 267 __t_est = (0.1 * __t_est) + (0.9 * t_delta); // low-pass filter | 287 __t_est = (0.1 * __t_est) + (0.9 * t_delta); // low-pass filter |
| 268 } else { | 288 } else { |
| 269 __t_est = t_delta; | 289 __t_est = t_delta; |
| 270 } | 290 } |
| 291 |
| 292 __t_frame_intervals.push(t_delta); |
| 293 |
| 271 var fps = 1000.0 / __t_est; | 294 var fps = 1000.0 / __t_est; |
| 272 document.title = "FPS: " + (fps | 0); | 295 document.title = "FPS: " + fps; |
| 273 | |
| 274 __t_est_total += t_delta; | |
| 275 __t_est_squared_total += t_delta * t_delta; | |
| 276 __t_count++; | |
| 277 } | 296 } |
| 278 __t_last = t_now; | 297 __t_last = t_now; |
| 279 } | 298 } |
| 280 | 299 |
| 281 // Returns true if a recorded gesture movement occured. | 300 // Returns true if a recorded gesture movement occured. |
| 282 function __advance_gesture_recording() { | 301 function __advance_gesture_recording() { |
| 283 var y = document.body.scrollTop; | 302 var y = document.body.scrollTop; |
| 284 // Only add a gesture if the scroll position changes. | 303 // Only add a gesture if the scroll position changes. |
| 285 if (__recording.length == 0 || y != __recording[__recording.length - 1].y) { | 304 if (__recording.length == 0 || y != __recording[__recording.length - 1].y) { |
| 286 var time_ms = new Date().getTime() - __t_start; | 305 var time_ms = __get_time() - __t_start; |
| 287 __recording.push({ time_ms: time_ms, y: y }); | 306 __recording.push({ time_ms: time_ms, y: y }); |
| 288 return true; | 307 return true; |
| 289 } | 308 } |
| 290 return false; | 309 return false; |
| 291 } | 310 } |
| 292 | 311 |
| 293 function __scroll_window_to(y) { | 312 function __scroll_window_to(y) { |
| 294 // Scrolls a window to a new location using window.scrollBy, but avoids | 313 // Scrolls a window to a new location using window.scrollBy, but avoids |
| 295 // window.scrollTo because of potential animation that may cause. This tracks | 314 // window.scrollTo because of potential animation that may cause. This tracks |
| 296 // the current scrollTop position to avoid forcing layout. | 315 // the current scrollTop position to avoid forcing layout. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 312 } | 331 } |
| 313 | 332 |
| 314 // Returns true if a gesture movement occured. | 333 // Returns true if a gesture movement occured. |
| 315 function __create_gesture_function(gestures) { | 334 function __create_gesture_function(gestures) { |
| 316 var i0 = 0; | 335 var i0 = 0; |
| 317 return function() { | 336 return function() { |
| 318 if (i0 >= gestures.length) { | 337 if (i0 >= gestures.length) { |
| 319 __stop(); | 338 __stop(); |
| 320 return false; | 339 return false; |
| 321 } | 340 } |
| 322 var time_cur = new Date().getTime() - __t_start; | 341 var time_cur = __get_time() - __t_start; |
| 323 if (time_cur <= gestures[i0].time_ms) | 342 if (time_cur <= gestures[i0].time_ms) |
| 324 return false; | 343 return false; |
| 325 | 344 |
| 326 // Skip any keyframes that we missed | 345 // Skip any keyframes that we missed |
| 327 for (i0; i0 < gestures.length && gestures[i0].time_ms < time_cur; ++i0); | 346 for (i0; i0 < gestures.length && gestures[i0].time_ms < time_cur; ++i0); |
| 328 | 347 |
| 329 // This loop overshoots by 1, so move back in time by 1 | 348 // This loop overshoots by 1, so move back in time by 1 |
| 330 i0--; | 349 i0--; |
| 331 var i1 = i0 + 1; | 350 var i1 = i0 + 1; |
| 332 | 351 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 }); | 389 }); |
| 371 } | 390 } |
| 372 return __create_gesture_function(gestures); | 391 return __create_gesture_function(gestures); |
| 373 } | 392 } |
| 374 | 393 |
| 375 function __sched_update() { | 394 function __sched_update() { |
| 376 __raf(function() { | 395 __raf(function() { |
| 377 __raf_is_live = true; | 396 __raf_is_live = true; |
| 378 // In case __raf falls back to using setTimeout, we must schedule the next | 397 // In case __raf falls back to using setTimeout, we must schedule the next |
| 379 // update before rendering the current update to help maintain the | 398 // update before rendering the current update to help maintain the |
| 380 // regularity of update intervals. | 399 // regularity of update frame_intervals. |
| 381 __sched_update(); | 400 __sched_update(); |
| 382 if (__running) { | 401 if (__running) { |
| 383 // Only update the FPS if a gesture movement occurs. Otherwise, the frame | 402 // Only update the FPS if a gesture movement occurs. Otherwise, the frame |
| 384 // rate average becomes inaccurate after any pause. | 403 // rate average becomes inaccurate after any pause. |
| 385 if (__advance_gesture()) | 404 if (__advance_gesture()) |
| 386 __update_fps(); | 405 __record_frame_time(); |
| 387 else | 406 else |
| 388 __t_last = new Date().getTime(); | 407 __t_last = __get_time(); |
| 389 } | 408 } |
| 390 }, document.body); | 409 }, document.body); |
| 391 } | 410 } |
| 392 | 411 |
| 393 function __start_recording() { | 412 function __start_recording() { |
| 394 __start(__advance_gesture_recording); | 413 __start(__advance_gesture_recording); |
| 395 } | 414 } |
| 396 | 415 |
| 397 function __make_body_composited() { | 416 function __make_body_composited() { |
| 398 document.body.style.webkitTransform = "translateZ(0)"; | 417 document.body.style.webkitTransform = "translateZ(0)"; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 412 } | 431 } |
| 413 else | 432 else |
| 414 gesture_function = __create_repeating_gesture_function( | 433 gesture_function = __create_repeating_gesture_function( |
| 415 __gestures[gesture_function]); | 434 __gestures[gesture_function]); |
| 416 } | 435 } |
| 417 else if (typeof gesture_function != "function") | 436 else if (typeof gesture_function != "function") |
| 418 throw new Error("Argument is not a function or gesture name"); | 437 throw new Error("Argument is not a function or gesture name"); |
| 419 | 438 |
| 420 __old_title = document.title; | 439 __old_title = document.title; |
| 421 __advance_gesture = gesture_function; | 440 __advance_gesture = gesture_function; |
| 422 __t_start = new Date().getTime(); | 441 __t_start = __get_time(); |
| 423 __running = true; | 442 __running = true; |
| 424 if (!__raf_is_live && !__animation) { | 443 if (!__raf_is_live && !__animation) { |
| 425 __sched_update(); | 444 __sched_update(); |
| 426 } | 445 } |
| 427 } | 446 } |
| 428 | 447 |
| 429 function __start_all() { | 448 function __start_all() { |
| 430 __queued_gesture_functions = []; | 449 __queued_gesture_functions = []; |
| 431 __results = { | 450 __results = { |
| 432 gestures: [], | 451 gestures: [], |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 __running = false; | 486 __running = false; |
| 468 __running_all = false; | 487 __running_all = false; |
| 469 document.title = __old_title; | 488 document.title = __old_title; |
| 470 document.body.scrollTop = 0; | 489 document.body.scrollTop = 0; |
| 471 __init_stats(); | 490 __init_stats(); |
| 472 } | 491 } |
| 473 | 492 |
| 474 function __force_compositor() { | 493 function __force_compositor() { |
| 475 document.body.style.webkitTransform = "translateZ(0)"; | 494 document.body.style.webkitTransform = "translateZ(0)"; |
| 476 } | 495 } |
| OLD | NEW |