Cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

requestAnimationFrame() memory leak

I've discovered that in SDK 6.0.0, requestAnimationFrame produced a memory leak when used as prescribed.

 

https://dev.fitbit.com/build/reference/device-api/globals/#requestanimationframe-

This method triggers an immediate screen update, and registers a callback to be invoked before painting this update. Note that the request expires after one frame. For continuous animations, another request should be made from within the first callback.

 

If you do this, your app will eventually crash, even if the function you pass into requestAnimationFrame() does nothing.

 

I solved it by putting a cancelAnimationFrame(requestID) inside of my clock tick callback with granularity set to seconds. This effectively skips 1 frame of animation every second.

 

I suspect that as each requestAnimationFrame callback calls a new requestAnimationFrame, the function chain can't be garbage collected and grows indefinitely. This is why canceling it and restarting it every second works.

 

This should be considered a bug, as the docs prescribe that you chain your requestAnimationFrame callbacks in this way and does not advise periodic canceling of the chain via cancelAnimationFrame().

 

I'm pretty sure this wasn't a problem on SDK 3 or 4. I used requestAnimationFrame loops all the time and never had an issue...

 

Here is an example app you can run to test this. See the comments for instructions:

 

import clock from "clock";
import { memory } from "system";

var frameID = null;

clock.granularity = "seconds";

clock.ontick = () => {
  console.log("JS memory: " + memory.js.used + "/" + memory.js.total + "/" + (memory.js.used/memory.js.total*100).toFixed(2) + "%");

  // Uncomment the next 2 lines to fix the memory leak.
  // cancelAnimationFrame(frameID);
  // animate();
}

function animate(){
  frameID = requestAnimationFrame(animate);
}

animate();

/* watch the console as the memory used % climbs until the app crashes.
 if there were no memory leak, the memory % would stabilize in a 4-6% range, probably between 14-20% total memory.
 uncomment the lines in the clock.ontick callback to fix the memory leak.
*/
Best Answer
0 Votes
0 REPLIES 0