Raphael: Gradual animation slowdown with simple in

2020-05-26 17:28发布

问题:

This question is similar in spirit to this other question, asked two years ago: Why does Raphael's framerate slow down on this code?

I'm using Raphael 2.1.0 in Chromium 25 in the following way:

<html>
<head>
  <title>Drawfun</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
  </style>
</head>
<body>
  <script src="raphael.js"></script>
  <script>
    var paper = Raphael(10, 50, 320, 200);
    var anim = Raphael.animation({transform: "R360"}, 500).repeat(Infinity);

    var rect = paper.rect(50, 40, 10, 20);
    rect.attr("fill", "#f00");
    rect.attr("stroke", "#fff");
    rect.animate(anim);
  </script>
</body> 
</html> 

Initially, the rectangle spins smoothly, as one would expect. After a minute or two, the rotation is running at ~15 FPS. After five or eight minutes, the animation is running at ~5 FPS.

Chrome CPU profiles indicate that as the animation becomes more choppy, the script is spending less and less time in (program) and more and more time in repush and eve.listeners.

The Chrome task manager doesn't indicate that there's a memory leak, either in the JS memory pool or in Chrome's, but does reveal that the page consumes more and more CPU over time.

When running that page in a recent version of Firefox, the animation becomes choppy much, much more quickly. These results have been verified on Linux and Windows, so it's not an OS issue :).

Does anyone have any insight into what might be wrong with either my code or Raphael's internals?

回答1:

Okay, I know this isn't exactly the answer that anyone wants to hear (and is a debatable cop-out), but from the look of Raphael, and the reading of the comments above, I can't help but think that this is a garbage collection issue, and is the reason for the varying results across everyone's browsers. From a quick glance over the Raphael source, it looks like quite a bit of vars are declared or implemented in the process of animating a frame, on a per frame basis. I know for a fact that at least in Chrome's V8 engine, each var is declared in a trackable method and put on the heap, the delay in the framerate reduction only further indicates that the garbage collector is kicking into high mode to free up chunks of declared vars that are no longer in use. I would bet good money that if you were to move a lot of the declarations in the Raphael script into a higher scope (maybe even global, gasp~!), specifically during the animation sequences you will find a very much improved frame-rate over the course of the script.

I ran into this problem on a custom implementation of an adaptation to webgl, basically i was making webgl commands work without webgl enabled. The rasterizer of the pipeline I built had a very similiar problem as this, basically it would draw the frames starting at 68fps, but by the end of the test, would be down to 13fps or lower, and at 98% processor use. It wasn't until I cleaned up every single declaration that created new memory allocations out of the pipeline scope (and did a few more well researched speed up tricks having to do with variable lookups) that I was finally able to keep up and produce a well written rasterizer that could pump about 3-5MB/s of pixels to the screen at a time while keeping a 50-60fps rate.

Again, not sure if this is the answer you want or need, but I think it is the correct one. :( Sorry I couldn't help any more than that. Good luck :)