30

I'm profiling the following code's memory usage using the Timeline in Chrome Dev Tools v27.

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv='content-type' content='text/html; charset=UTF-8' />
  <title>RAF</title>
</head>
  <body>
    <script type='text/javascript' charset='utf-8'>
      var frame = function() {
        window.webkitRequestAnimationFrame(frame);
      };
      window.webkitRequestAnimationFrame(frame);
    </script>
  </body>
</html>

Notice it's simple. But eventually I see the a tooth pattern appear that indicates the garbage collector is reclaiming memory.

Chrome Dev Tools Timeline

Does raf create garbage objects by default? Is there any way to avoid this? Thx.

HIRA THAKUR
  • 17,189
  • 14
  • 56
  • 87
Vince
  • 589
  • 9
  • 16
  • Related. There appear to be more potential issues in this area. I would advise perhaps to take this whole memory monitoring tool's output with a grain of salt? Honestly, I'm not really sure what to conclude from any of this. http://stackoverflow.com/questions/19395565/chrome-requestanimationframe-issues – Steven Lu Oct 16 '13 at 05:05
  • Im gonna put up a bounty on this one if anybody else is willing to do the same :> was already thinking if it might help to have two functions flip flop registering each other. – Manuel Arwed Schmidt Apr 17 '14 at 00:16

3 Answers3

7

enter image description here

I have found out the following: If you change your RAF function into two "ping-pong" like functions, you get alot less garbage. You can't avoid the first initial "big GC", but after that you see only minor GCs of about 50kb instead of 700kb-1mb GCs. The code will look like this:

<script type='text/javascript' charset='utf-8'>
  window.frameA = function() {
    window.webkitRequestAnimationFrame(window.frameB);
  };
  window.frameB = function() {
    window.webkitRequestAnimationFrame(window.frameA);
  };
  window.webkitRequestAnimationFrame(window.frameA);
</script>

I guess this is the best you can do in Chrome. I noticed that in FF the gc intervals or memory hardly changes, so its probably related to the chrome debugging stuff (see the linked chrome bug report above for more details). However, I noticed an improvement in my own game when deploying RAF like this - and heck I need to be able to debug it without artificial GCs that won't happen on normal users machines.

Manuel Arwed Schmidt
  • 3,376
  • 2
  • 18
  • 28
  • 2
    I am shocked to say this works. Amazing find, I can't even imagine what made you try this. :) – Jaruba Jan 27 '16 at 12:12
  • 1
    Kevzettler: It was always a hack that would (hopefully) become obsolete one day. Can you tell us which Browserversion you tested this? Do you still observe the gc problem in general? I'll edit the answer accordingly. – Manuel Arwed Schmidt Mar 17 '16 at 19:26
5

i think Chrome may have an issue there...

similar bug is already reported here:

https://code.google.com/p/chromium/issues/detail?id=120186

tszarzynski
  • 604
  • 7
  • 15
3

It looks like a retain cycle. Frame is calling itself so holds a retain count and doesn't get released. Also any time you are monitoring running code either with profile, timeline or heap stacks there are going to be some side-effects.

Either way I wouldn't worry about it. There are much larger issues to address if you're trying to get your app or page performant. As long as JS completes in under 16ms, no one will ever notice anything.

The biggest memory/CPU issues are: network calls, decompressing PNGs/JPGs, creating and destroying DOM elements, processing/parsing data on a non-worker thread, poor use of GPU textures and allocating lots of data to cause the GC to take a long time to collect data.

I was able to optimize a scroll list with 1,000,000 items to run at 120FPS on chrome (https://github.com/puppybits/BackboneJS-PerfView). The performance tools should help you find the largest issues that the user can see and you don't need to worry about the minor things.

puppybits
  • 1,110
  • 12
  • 16