tag - javascript yes no dialog
Perfil específico de animación CPU (4)
La situación y el problema.
Tengo varias animaciones (css y javascript / jQuery) en mi sitio y a veces hace que mi sitio sea tartamudo.
Mi pregunta
¿Cómo puedo ver la cantidad de CPU específica que usa una animación (tanto CSS, JavaScript como jQuery) en tiempo de ejecución y tiempo de ejecución?
Sé cómo puedo ver el uso completo de la CPU del sitio, pero no para una animación específica.
Haga clic en F12, Ir a perfiles, haga clic en Inicio. Recargar página.
Espere hasta que se recargue la página y haga clic en Detener.
Haga clic en su perfil y vea el resultado (Y)
Prefacio: Esta no es una respuesta "completa", como tal, sino más bien la mejor que podría encontrar dentro de un tiempo razonable. Me pareció una pena no publicar mis resultados a pesar de que no son la respuesta perfecta ...
También cubre solo jQuery.animate
; No investigué las animaciones de CSS.
Para jQuery, al menos, esto es difícil; no es como el navegador "sabe" acerca de una animación jQuery. Efectivamente, todo lo que jQuery hace es programar una función para ejecutarse n veces con setTimeout()
o setInterval()
, donde cada llamada de función mueve el elemento unos pocos píxeles (o cambia algo un poco más), dando la ilusión de animaciones suaves.
Su navegador tendría, de alguna manera, que hacer un seguimiento de qué función de llamada pertenece a qué animación. Ya que estas son funciones anónimas, esto no es realmente fácil ... Se podría usar algún tipo de declaración de depuración especial, pero AFAIK ningún navegador implementa una característica como esta.
Lo que podemos hacer es medir el número de actualizaciones que jQuery.animate
realiza con el step
devolución de llamada:
Una función a llamar para cada propiedad animada de cada elemento animado. Esta función brinda la oportunidad de modificar el objeto Tween para cambiar el valor de la propiedad antes de que se establezca.
Esto solo te dará una aproximación , en el mejor de los casos. Pero tal vez sea lo suficientemente bueno; He creado un ejemplo (ver más abajo), que me da estos resultados en mi sistema:
"a: 52 updates; 26 upd/s"
"b: 27 updates; 54 upd/s"
"c: 1080 updates; 360 upd/s"
Su sistema puede variar, pero sugiere que:
-
a
era el más barato; -
b
era un poco más caro, pero también bastante barato -
c
es varias veces más caro quea
ob
.
Para comprobar si esto es más o menos preciso, solo habilité una animación a la vez y verifiqué si esto corresponde a lo que informan las herramientas de desarrollo de Chromium y Firefox:
- Cromo:
a
40ms gastado no inactivo; Firefox: 2 llamadas an.fx.tick
- Cromo:
b
pasó 40ms no inactivo; Firefox: 4 llamadas an.fx.tick
- Cromo:
c
gastado 130ms no inactivo; Firefox: 36 llamadas an.fx.tick
Lo que es más o menos exacto, aunque no del todo.
¿Será esto suficientemente útil para su aplicación? No tengo idea. Tal vez tal vez no...
Prueba de HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Animations test</title>
<style>
div { width: 200px; height: 100px; position: relative; color: #fff; }
#test_a { background-color: green; }
#test_b { background-color: red; }
#test_c { background-color: blue; }
</style>
</head>
<body>
<div id="test_a"></div>
<div id="test_b"></div>
<div id="test_c"></div>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="anim.js"></script>
</body>
</html>
Prueba JS en CoffeeScript:
go = ->
a = b = c = 0
log = (n, t) ->
eval "u = #{n}"
str = "#{n}: #{u} updates; #{parseInt u / t, 10} upd/s"
$("#test_#{n}").html str
console.log str
$(''#test_a'').animate {left: ''500px''},
duration: 500
step: -> a += 1
complete: -> log ''a'', .5
$(''#test_b'').animate {top: ''100px'', left: ''100px'', opacity: 0.3, width: ''500px''},
duration: 200
step: -> b += 1
complete: -> log ''b'', 2
$(''#test_c'').animate {left: ''500px'', top: ''300px'', opacity: .75, height: ''50px'', width: ''400px''},
duration: 3000
step: -> c += 1
complete: -> log ''c'', 3
$(document).ready -> setTimeout go, 500
Y el mismo JS compilado por conveniencia:
// Generated by CoffeeScript 1.7.1
(function() {
var go;
go = function() {
var a, b, c, log;
a = b = c = 0;
log = function(n, t) {
var str;
eval("u = " + n);
str = "" + n + ": " + u + " updates; " + (parseInt(u / t, 10)) + " upd/s";
$("#test_" + n).html(str);
return console.log(str);
};
$(''#test_a'').animate({
left: ''500px''
}, {
duration: 500,
step: function() {
return a += 1;
},
complete: function() {
return log(''a'', .5);
}
});
return;
$(''#test_b'').animate({
top: ''100px'',
left: ''100px'',
opacity: 0.3,
width: ''500px''
}, {
duration: 200,
step: function() {
return b += 1;
},
complete: function() {
return log(''b'', 2);
}
});
return $(''#test_c'').animate({
left: ''500px'',
top: ''300px'',
opacity: .75,
height: ''50px'',
width: ''400px''
}, {
duration: 3000,
step: function() {
return c += 1;
},
complete: function() {
return log(''c'', 3);
}
});
};
$(document).ready(function() {
return setTimeout(go, 500);
});
}).call(this);
Puede intentar ejecutar una instancia de console.profile()
al inicio de cada animación jQuery y luego deshabilitar las animaciones una por una para depurar.
No puedes hacer un perfil de las animaciones CSS, que yo sepa. Solo los valores de inicio y final son accesibles a través de JavaScript.
function AnimateRotate(elem, angle, dur) {
var $elem = $(elem);
// we use a pseudo object for the animation
// (starts from `0` to `angle`), you can name it as you want
$({
deg: 0
}).animate({
deg: angle
}, {
duration: dur,
step: function(now) {
// in the step-callback (that is fired each step of the animation),
// you can use the `now` paramter which contains the current
// animation-position (`0` up to `angle`)
$elem.css({
transform: ''rotate('' + now + ''deg)''
});
}
});
}
$(''#1'').click(function() {
console.profile(''Animation #1'');
$(this).animate({
''height'': ''100px'',
''width'': ''100px''
}, function() {
console.profileEnd(''Animation #1'');
});
});
$(''#2'').click(function() {
console.profile(''Animation #2'');
AnimateRotate(this, 3000, 400);
$(this).animate({
''height'': ''300px'',
''width'': ''300px''
}, function() {
console.profileEnd(''Animation #2'');
});
});
div {
height: 10px;
width: 10px;
background-color: red;
transform-origin: 60% 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="1"></div>
<br>
<div id="2"></div>
Tal vez podría usted console.profile () con Firefox. http://www.stoimen.com/blog/2010/02/02/profiling-javascript-with-firebug-console-profile-console-time/
Coloque console.profile()
antes de la función que desea medir y console.profileEnd()
después del método.
<html>
<body>
<script>
myFunc = function() {
var a = [];
}
console.profile();
myFunc();
console.profileEnd();
</script>
</body>
</html>
https://developer.chrome.com/devtools/docs/console-api Aquí encontrará algunos métodos más para la depuración.
Edición: Acabo de encontrar otro sitio con información útil para la extensión de firebug: https://getfirebug.com/wiki/index.php/Console.profile