Commit cd92ffb4 authored by alancutter's avatar alancutter Committed by Commit bot

Add CSS Transitions performance tests

This adds several performance tests for CSS Transitions
initiated in various ways.

BUG=309981,421733

Review URL: https://codereview.chromium.org/399393002

Cr-Commit-Position: refs/heads/master@{#299417}
parent a3434da0
...@@ -15,7 +15,7 @@ class ToughAnimationCasesPage(page_module.Page): ...@@ -15,7 +15,7 @@ class ToughAnimationCasesPage(page_module.Page):
def RunNavigateSteps(self, action_runner): def RunNavigateSteps(self, action_runner):
action_runner.NavigateToPage(self) action_runner.NavigateToPage(self)
if self._need_measurement_ready: if self._need_measurement_ready:
action_runner.WaitForJavaScriptCondition('measurementReady') action_runner.WaitForJavaScriptCondition('window.measurementReady')
def RunSmoothness(self, action_runner): def RunSmoothness(self, action_runner):
action_runner.Wait(10) action_runner.Wait(10)
...@@ -54,7 +54,55 @@ class ToughAnimationCasesPageSet(page_set_module.PageSet): ...@@ -54,7 +54,55 @@ class ToughAnimationCasesPageSet(page_set_module.PageSet):
# animatable properties. # animatable properties.
'file://tough_animation_cases/balls_css_transition_all_properties.html', 'file://tough_animation_cases/balls_css_transition_all_properties.html',
# pylint: disable=C0301 # pylint: disable=C0301
'file://tough_animation_cases/overlay_background_color_css_transitions.html' 'file://tough_animation_cases/overlay_background_color_css_transitions.html',
# Why: Tests many CSS Transitions all starting at the same time triggered
# by inserting new elements.
# pylint: disable=C0301
'file://tough_animation_cases/css_transitions_simultaneous_by_inserting_new_elements.html?N=0316',
# Why: Tests many CSS Transitions all starting at the same time triggered
# by inserting style sheets.
# pylint: disable=C0301
'file://tough_animation_cases/css_transitions_simultaneous_by_inserting_style_element.html?N=0316',
# Why: Tests many CSS Transitions all starting at the same time triggered
# by updating class.
# pylint: disable=C0301
'file://tough_animation_cases/css_transitions_simultaneous_by_updating_class.html?N=0316',
# Why: Tests many CSS Transitions all starting at the same time triggered
# by updating inline style.
# pylint: disable=C0301
'file://tough_animation_cases/css_transitions_simultaneous_by_updating_inline_style.html?N=0316',
# Why: Tests many CSS Transitions chained together using events at
# different times triggered by inserting new elements.
# pylint: disable=C0301
'file://tough_animation_cases/css_transitions_staggered_chaining_by_inserting_new_element.html?N=0316',
# Why: Tests many CSS Transitions chained together using events at
# different times triggered by inserting style sheets.
# pylint: disable=C0301
'file://tough_animation_cases/css_transitions_staggered_chaining_by_inserting_style_element.html?N=0316',
# Why: Tests many CSS Transitions chained together using events at
# different times triggered by updating class.
# pylint: disable=C0301
'file://tough_animation_cases/css_transitions_staggered_chaining_by_updating_class.html?N=0316',
# Why: Tests many CSS Transitions chained together using events at
# different times triggered by updating inline style.
# pylint: disable=C0301
'file://tough_animation_cases/css_transitions_staggered_chaining_by_updating_inline_style.html?N=0316',
# Why: Tests many CSS Transitions starting at different times triggered by
# inserting new elements.
# pylint: disable=C0301
'file://tough_animation_cases/css_transitions_staggered_triggering_by_inserting_new_element.html?N=0316',
# Why: Tests many CSS Transitions starting at different times triggered by
# inserting style sheets.
# pylint: disable=C0301
'file://tough_animation_cases/css_transitions_staggered_triggering_by_inserting_style.html?N=0316',
# Why: Tests many CSS Transitions starting at different times triggered by
# updating class.
# pylint: disable=C0301
'file://tough_animation_cases/css_transitions_staggered_triggering_by_updating_class.html?N=0316',
# Why: Tests many CSS Transitions starting at different times triggered by
# updating inline style.
# pylint: disable=C0301
'file://tough_animation_cases/css_transitions_staggered_triggering_by_updating_inline_style.html?N=0316',
] ]
for url in urls_list_one: for url in urls_list_one:
......
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="stylesheet" type="text/css" href="resources/tablet.css">
<link rel="stylesheet" type="text/css" href="resources/transition.css">
<script src="resources/perftesthelper.js"></script>
<style>
target {
opacity: 0;
}
trigger + target {
transition: none;
opacity: 1;
}
trigger {
display: none;
}
</style>
<container id="container"></container>
<script>
var N = PerfTestHelper.getN(1000);
var duration = 1000;
var targets = [];
var triggers = [];
for (var i = 0; i < N; i++) {
triggers.push(document.createElement('trigger'));
var target = document.createElement('target');
container.appendChild(target);
targets.push(target);
}
function startAllTransitions() {
requestAnimationFrame(function() {
targets.forEach(function(target, i) {
container.insertBefore(triggers[i], target);
});
requestAnimationFrame(function() {
triggers.forEach(function(trigger) {
trigger.remove();
})
});
});
}
requestAnimationFrame(startAllTransitions);
setInterval(startAllTransitions, duration);
PerfTestHelper.signalReady();
</script>
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="stylesheet" type="text/css" href="resources/tablet.css">
<link rel="stylesheet" type="text/css" href="resources/transition.css">
<script src="resources/perftesthelper.js"></script>
<container id="container"></container>
<script>
var N = PerfTestHelper.getN(1000);
var duration = 1000;
var style = null;
var keyframe = 1;
var keyframeValues = [0, 1]
for (var i = 0; i < N; i++) {
container.appendChild(document.createElement('target'));
}
function startAllTransitions() {
keyframe ^= 1;
if (style) {
style.remove();
}
style = document.createElement('style');
style.textContent = 'target { opacity: ' + keyframeValues[keyframe] + '; }';
container.appendChild(style);
}
requestAnimationFrame(startAllTransitions);
setInterval(startAllTransitions, duration);
PerfTestHelper.signalReady();
</script>
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="stylesheet" type="text/css" href="resources/tablet.css">
<link rel="stylesheet" type="text/css" href="resources/transition.css">
<script src="resources/perftesthelper.js"></script>
<style>
.keyframe0 {
opacity: 0;
}
.keyframe1 {
opacity: 1;
}
</style>
<container id="container"></container>
<script>
var N = PerfTestHelper.getN(1000);
var duration = 1000;
var keyframe = 1;
var targets = [];
for (var i = 0; i < N; i++) {
var target = document.createElement('target');
container.appendChild(target);
targets.push(target);
}
function startAllTransitions() {
keyframe ^= 1;
targets.forEach(function(target) {
target.className = 'keyframe' + keyframe;
});
}
requestAnimationFrame(startAllTransitions);
setInterval(startAllTransitions, duration);
PerfTestHelper.signalReady();
</script>
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="stylesheet" type="text/css" href="resources/tablet.css">
<link rel="stylesheet" type="text/css" href="resources/transition.css">
<script src="resources/perftesthelper.js"></script>
<container id="container"></container>
<script>
var N = PerfTestHelper.getN(1000);
var duration = 1000;
var targets = [];
var keyframe = 1;
var keyframeValues = [0, 1]
for (var i = 0; i < N; i++) {
var target = document.createElement('target');
container.appendChild(target);
targets.push(target);
}
function startAllTransitions() {
keyframe ^= 1;
targets.forEach(function(target) {
target.style.opacity = keyframeValues[keyframe];
});
}
requestAnimationFrame(startAllTransitions);
setInterval(startAllTransitions, duration);
PerfTestHelper.signalReady();
</script>
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="stylesheet" type="text/css" href="resources/tablet.css">
<link rel="stylesheet" type="text/css" href="resources/transition.css">
<script src="resources/perftesthelper.js"></script>
<style>
keyframe0 + target {
opacity: 0;
}
keyframe1 + target {
opacity: 1;
}
keyframe0, keyframe1 {
display: none;
}
</style>
<container id="container"></container>
<script>
var N = PerfTestHelper.getN(1000);
var duration = 1000;
var keyframeValues = [0, 1];
var keyframeStash = [[], []];
var targets = [];
for (var i = 0; i < N; i++) {
keyframeStash[0].push(document.createElement('keyframe0'));
keyframeStash[1].push(document.createElement('keyframe1'));
var target = document.createElement('target');
target._keyframe = 0;
target.style.transitionDelay = (-i / N * duration) + 'ms';
container.appendChild(target);
target.addEventListener('transitionend', restartTransition);
targets.push(target);
}
function restartTransition(event) {
var target = event.target;
target.style.removeProperty('transition-delay');
keyframeStash[target._keyframe].push(target.previousSibling);
target.previousSibling.remove();
target._keyframe ^= 1;
container.insertBefore(keyframeStash[target._keyframe].pop(), target);
}
requestAnimationFrame(function() {
targets.forEach(function(target) {
container.insertBefore(keyframeStash[0].pop(), target);
});
});
PerfTestHelper.signalReady();
</script>
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="stylesheet" type="text/css" href="resources/tablet.css">
<link rel="stylesheet" type="text/css" href="resources/transition.css">
<script src="resources/perftesthelper.js"></script>
<style>
target {
opacity: 0;
}
</style>
<container id="container"></container>
<script>
var N = PerfTestHelper.getN(500);
var duration = 1000;
var keyframeValues = [0, 1];
var id = 0;
for (var i = 0; i < N; i++) {
var target = document.createElement('target');
target._keyframe = 0;
target.style.transitionDelay = (-i / N * duration) + 'ms';
container.appendChild(target);
target.addEventListener('transitionend', restartTransition);
}
function restartTransition(event) {
event.target._keyframe ^= 1;
addNewIDStyle(event.target);
event.target.style.removeProperty('transition-delay');
}
function addNewIDStyle(target) {
id++;
if (target._currentIDStyle) {
target._currentIDStyle.remove();
}
var style = document.createElement('style');
style.textContent = '#id' + id + ' { opacity: ' + keyframeValues[target._keyframe] + ';}';
container.appendChild(style);
target.id = 'id' + id;
target._currentIDStyle = style;
}
requestAnimationFrame(function() {
var styleRule = document.styleSheets[2].rules[0].style;
styleRule.opacity = keyframeValues[1];
requestAnimationFrame(function() {
styleRule.opacity = keyframeValues[0];
});
});
PerfTestHelper.signalReady();
</script>
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="stylesheet" type="text/css" href="resources/tablet.css">
<link rel="stylesheet" type="text/css" href="resources/transition.css">
<script src="resources/perftesthelper.js"></script>
<style>
target {
opacity: 0;
}
.keyframe0 {
opacity: 0;
}
.keyframe1 {
opacity: 1;
}
</style>
<container id="container"></container>
<script>
var N = PerfTestHelper.getN(1000);
var duration = 1000;
var keyframeValues = [0, 1];
for (var i = 0; i < N; i++) {
var target = document.createElement('target');
target._keyframe = 0;
target.style.transitionDelay = (-i / N * duration) + 'ms';
container.appendChild(target);
target.addEventListener('transitionend', restartTransition);
}
function restartTransition(event) {
event.target._keyframe ^= 1;
event.target.className = 'keyframe' + event.target._keyframe;
event.target.style.removeProperty('transition-delay');
}
requestAnimationFrame(function() {
var styleRule = document.styleSheets[2].rules[0].style;
styleRule.opacity = keyframeValues[1];
requestAnimationFrame(function() {
styleRule.opacity = keyframeValues[0];
});
});
PerfTestHelper.signalReady();
</script>
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="stylesheet" type="text/css" href="resources/tablet.css">
<link rel="stylesheet" type="text/css" href="resources/transition.css">
<script src="resources/perftesthelper.js"></script>
<style>
target {
opacity: 0;
}
</style>
<container id="container"></container>
<script>
var N = PerfTestHelper.getN(1000);
var duration = 1000;
var keyframeValues = [0, 1];
for (var i = 0; i < N; i++) {
var target = document.createElement('target');
target._keyframe = 0;
target.style.transitionDelay = (-i / N * duration) + 'ms';
container.appendChild(target);
target.addEventListener('transitionend', restartTransition);
}
function restartTransition(event) {
event.target._keyframe ^= 1;
event.target.style.opacity = keyframeValues[event.target._keyframe];
event.target.style.removeProperty('transition-delay');
}
requestAnimationFrame(function() {
var styleRule = document.styleSheets[2].rules[0].style;
styleRule.opacity = keyframeValues[1];
requestAnimationFrame(function() {
styleRule.opacity = keyframeValues[0];
});
});
PerfTestHelper.signalReady();
</script>
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="stylesheet" type="text/css" href="resources/tablet.css">
<link rel="stylesheet" type="text/css" href="resources/transition.css">
<script src="resources/perftesthelper.js"></script>
<style>
show + target {
opacity: 1;
}
hide + target {
opacity: 0;
}
show, hide {
display: none;
}
</style>
<container id="container"></container>
<script>
var N = PerfTestHelper.getN(1000);
var duration = 1000;
var stash = {SHOW: [], HIDE: []};
var targets = [];
for (var i = 0; i < N; i++) {
stash.HIDE.push(document.createElement('hide'));
var show = document.createElement('show');
container.appendChild(show);
var target = document.createElement('target');
container.appendChild(target);
targets.push(target);
}
function startTransition(target, fastForward) {
var state = target.previousSibling;
stash[state.tagName].push(state);
state.remove();
var newState = state.tagName == 'SHOW' ? stash.HIDE.pop() : stash.SHOW.pop();
container.insertBefore(newState, target);
target.style.transitionDelay = -fastForward + 'ms';
}
requestAnimationFrame(function(time) {
var startTime = time - duration;
var step = 0;
function staggeredStart(time) {
var elapsed = time - startTime;
var targetStep = Math.floor(N * elapsed / duration);
step = Math.max(targetStep - N, step);
for (; step < targetStep; step++) {
startTransition(targets[step % N], elapsed - (step / N * duration));
}
requestAnimationFrame(staggeredStart);
}
staggeredStart(time);
});
PerfTestHelper.signalReady();
</script>
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="stylesheet" type="text/css" href="resources/tablet.css">
<link rel="stylesheet" type="text/css" href="resources/transition.css">
<script src="resources/perftesthelper.js"></script>
<container id="container"></container>
<script>
var N = PerfTestHelper.getN(1000);
var duration = 1000;
var targets = [];
var styles = [];
var keyframeValues = [0, 1];
for (var i = 0; i < N; i++) {
var target = document.createElement('target');
target._keyframe = 0;
container.appendChild(target);
targets.push(target);
}
function addNewClassStyle(step) {
// Clean up overwritten styles.
var i = 0;
for (; i < styles.length && styles[i].lastStep < step; i++) {
styles[i].style.remove();
}
styles.splice(0, i);
var style = document.createElement('style');
var className = 'style' + step + 'keyframe';
style.textContent = '.' + className + '0 { opacity: ' + keyframeValues[0] + '; }\n';
style.textContent += '.' + className + '1 { opacity: ' + keyframeValues[1] + '; }\n';
container.appendChild(style);
styles.push({
style: style,
lastStep: step + N,
});
return className;
}
function startTransitions(startingTargets, startStep, endStep) {
var newClassName = addNewClassStyle(startStep, endStep);
startingTargets.forEach(function(startInfo) {
startInfo.target._keyframe ^= 1;
startInfo.target.className = newClassName + startInfo.target._keyframe;
startInfo.target.style.transitionDelay = -startInfo.fastForward + 'ms';
});
}
requestAnimationFrame(function(time) {
var startTime = time - duration;
var previousStep = 0;
function staggeredStart(time) {
var elapsed = time - startTime;
var targetStep = Math.floor(N * elapsed / duration);
var restartingTargets = [];
for (var step = Math.max(targetStep - N, previousStep); step < targetStep; step++) {
var stepStartTime = step / N * duration;
restartingTargets.push({
target: targets[step % N],
fastForward: elapsed - stepStartTime,
});
}
startTransitions(restartingTargets, targetStep);
previousStep = targetStep;
requestAnimationFrame(staggeredStart);
}
staggeredStart(time);
});
PerfTestHelper.signalReady();
</script>
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="stylesheet" type="text/css" href="resources/tablet.css">
<link rel="stylesheet" type="text/css" href="resources/transition.css">
<script src="resources/perftesthelper.js"></script>
<style>
.keyframe0 {
opacity: 0;
}
.keyframe1 {
opacity: 1;
}
</style>
<container id="container"></container>
<script>
var N = PerfTestHelper.getN(1000);
var duration = 1000;
var targets = [];
for (var i = 0; i < N; i++) {
var target = document.createElement('target');
target._keyframe = 1;
target.className = 'keyframe' + target._keyframe;
container.appendChild(target);
targets.push(target);
}
function startTransition(target, fastForward) {
target._keyframe ^= 1;
target.className = 'keyframe' + target._keyframe;
target.style.transitionDelay = -fastForward + 'ms';
}
requestAnimationFrame(function(time) {
var startTime = time - duration;
var step = 0;
function staggeredStart(time) {
var elapsed = time - startTime;
var targetStep = Math.floor(N * elapsed / duration);
step = Math.max(targetStep - N, step);
for (; step < targetStep; step++) {
startTransition(targets[step % N], elapsed - (step / N * duration));
}
requestAnimationFrame(staggeredStart);
}
staggeredStart(time);
});
PerfTestHelper.signalReady();
</script>
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="stylesheet" type="text/css" href="resources/tablet.css">
<link rel="stylesheet" type="text/css" href="resources/transition.css">
<script src="resources/perftesthelper.js"></script>
<container id="container"></container>
<script>
var N = PerfTestHelper.getN(1000);
var duration = 1000;
var targets = [];
var keyframeValues = [0, 1];
for (var i = 0; i < N; i++) {
var target = document.createElement('target');
target._keyframe = 1;
target.style.opacity = keyframeValues[target._keyframe];
container.appendChild(target);
targets.push(target);
}
function startTransition(target, fastForward) {
target._keyframe ^= 1;
target.style.opacity = keyframeValues[target._keyframe];
target.style.transitionDelay = -fastForward + 'ms';
}
requestAnimationFrame(function(time) {
var startTime = time - duration;
var step = 0;
function staggeredStart(time) {
var elapsed = time - startTime;
var targetStep = Math.floor(N * elapsed / duration);
step = Math.max(targetStep - N, step);
for (; step < targetStep; step++) {
startTransition(targets[step % N], elapsed - (step / N * duration));
}
requestAnimationFrame(staggeredStart);
}
staggeredStart(time);
});
PerfTestHelper.signalReady();
</script>
...@@ -59,7 +59,7 @@ body { ...@@ -59,7 +59,7 @@ body {
</style> </style>
<script src="resources/perftesthelper.js"></script> <script src="resources/perftesthelper.js"></script>
<script> <script>
var measurementReady = false; window.measurementReady = false;
var maxOverlays = 500; var maxOverlays = 500;
var colors = ["rgba(204, 0, 0, 0.5)", "rgba(255, 204, 0, 0.5)", "rgba(170, 255, 0, 0.5)" var colors = ["rgba(204, 0, 0, 0.5)", "rgba(255, 204, 0, 0.5)", "rgba(170, 255, 0, 0.5)"
, "rgba(0, 153, 204, 0.5)", "rgba(25, 76, 153, 0.5)", "rgba(102, 25, 153, 0.5)"]; , "rgba(0, 153, 204, 0.5)", "rgba(25, 76, 153, 0.5)", "rgba(102, 25, 153, 0.5)"];
...@@ -75,7 +75,7 @@ window.onload = function () { ...@@ -75,7 +75,7 @@ window.onload = function () {
overlays.push(overlay); overlays.push(overlay);
} }
measurementReady = true; window.measurementReady = true;
} }
function Overlay() function Overlay()
......
...@@ -23,4 +23,26 @@ window.PerfTestHelper.random = function() { ...@@ -23,4 +23,26 @@ window.PerfTestHelper.random = function() {
return (randomSeed & 0xfffffff) / 0x10000000; return (randomSeed & 0xfffffff) / 0x10000000;
}; };
window.PerfTestHelper.getN = function(defaultN) {
var match = /N=(\d+)/.exec(window.location.search);
if (match) {
return Number(match[1]);
}
if (typeof defaultN === 'undefined') {
throw 'Default N value required';
}
return defaultN;
};
window.PerfTestHelper.signalReady = function() {
requestAnimationFrame(function() {
// FIXME: We must wait at least two frames before
// measuring to allow the GC to clean up the
// previous test.
requestAnimationFrame(function() {
window.measurementReady = true;
});
});
};
})(); })();
/* Copyright 2014 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.
*/
body {
margin: 0;
overflow: hidden;
}
container {
display: flex;
flex-flow: row wrap;
width: 550px;
height: 800px;
background-color: lightgrey;
}
target {
display: inline-block;
width: 11px;
height: 11px;
background: green;
}
/* Copyright 2014 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.
*/
target {
transition: opacity 1000ms linear;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment