Profile specific animation CPU

旧城冷巷雨未停 提交于 2019-11-30 05:52:30

Click F12, Go to profiles, click on start. Reload page.

Wait untill your page reloaded, and click stop.

Click on your profile and see result (Y)

Preface: This is not a "complete" answer, as such, but rather the best I could come up within a reasonable amount of time. It seemed a shame to not post my results even though they're not a perfect answer...

It also only covers jQuery.animate; I did not investigate CSS animations.


For jQuery, at least, this is difficult; it's not like the browser "knows" about a jQuery animation. Effectively, all jQuery does is schedule a function to run n times with setTimeout() or setInterval(), where each function call moves the element by a few pixels (or changed something else a little bit), giving the illusion of smooth animations.

Your browser would, somehow, have to keep track of which function call belongs to which animation. Since these are anonymous functions, this is not really easy... Some sort of special debugging statement could be used, but AFAIK no browser implements a feature like this.

What we can do is measure the number of updates jQuery.animate does with the step callback:

A function to be called for each animated property of each animated element. This function provides an opportunity to modify the Tween object to change the value of the property before it is set.

This will only give you an approximation, at best. But perhaps it's good enough; I've created an example (see below), which gives me these results on my system:

"a: 52 updates; 26 upd/s"
"b: 27 updates; 54 upd/s"
"c: 1080 updates; 360 upd/s"

Your system might vary, but suggests that:

  • a was the cheapest;
  • b was slightly more exensive, but also actually quite cheap
  • c is several times more expensive than a or b.

To check if this is roughly accurate, I enabled only one animation at a time, and checked if this corresponds to what Chromium & Firefox developer tools report:

  • Chromium: a spent 40ms non-idle; Firefox: 2 calls to n.fx.tick
  • Chromium: b spent 40ms non-idle; Firefox: 4 calls to n.fx.tick
  • Chromium: c spent 130ms non-idle; Firefox: 36 calls to n.fx.tick

Which is indeed roughly accurate, though not entirely.

Will this be useful enough for your application? I have no idea. Maybe, maybe not...



Test 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>

Test JS in 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

And the same JS compiled for convenience:

// 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);
Wouter den Ouden

Maybe you could you console.profile() with Firefox. http://www.stoimen.com/blog/2010/02/02/profiling-javascript-with-firebug-console-profile-console-time/

Put console.profile() before the function you want to measure and console.profileEnd() after the method.

<html>
  <body>
    <script>
      myFunc = function() {
        var a = [];
      }             

      console.profile();
      myFunc();
      console.profileEnd();
    </script>
  </body>
</html>

https://developer.chrome.com/devtools/docs/console-api Here you find some more methods for debugging.

Edit: I've just found another site with useful information for the firebug extension: https://getfirebug.com/wiki/index.php/Console.profile

You can try running a console.profile() instance at the start of each jQuery animation and then disable animations one at a time to debug.

You cannot profile CSS animations as far as I know. Only the starting and ending values are accessible via 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>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!