title: canvas performance when drawing massive amount of images
body: <p>I am about to draw many stars, like 10000 in canvas and continuouslly creating new one and fade out the old one.</p>
  
  <p>Here is my thinking:</p>
  
  <ol>
  <li>create some stars per frame</li>
  <li>draw all stars per frame</li>
  <li>when star count reaches threshold, create a new canvas and leave the old canvas alone, empty star list. And from now, drawing stars in new canvas. This will make browser only drawing the max count of stars and looks like there are much more stars.</li>
  <li>when canvas count reaches threshold, just fade out and remove the very first one.</li>
  </ol>
  
  <p>So there are always new stars created and old stars faded out, also high performance.</p>
  
  <p>But after running about 1 minute, the fps suddenly became very low, what's the problem in there?</p>
  
  <p>Here are my code sample below (<strong>only run in full-page mode will cause the problem, and I don't know why. Tested in Chrome 58</strong>):</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>var container, star, starCtx,
      starList = [],
      starShapeList = [],
      canvasList = [],
      starSize = 22,
      maxCanvasCount = 10,
      starCountPerCanvas = 500;
  var width = window.innerWidth, height = window.innerHeight;
  
  init();
  
  function init() {
      container = document.createElement('div');
  
      // for drawing stars
      starCtx = createCanvas();
  
      star = document.createElement('img');
      star.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAMAAADzapwJAAAAM1BMVEX/hAD/hQD1kA3+hQHykxH7iQbXsDDVsTHqnBnrmxjPtzjGwkTKvT7WsDC7zE++yUzNuTrg0dc+AAAAEXRSTlMBBhELFg0mMCAaOVNGH3psPn/xpHgAAACMSURBVBjTndBLDsMgDEXR5vFsbCCf/a+2CahYidRJ7vAIYcznXUvvadFdU294KCAAKN0nC1eCvuLyqUmo6q4KST+/FNRiuRhPDwZoR2vFnAgWrprbvrec1TEZpx5122q5cQLdSq3zkhhpJT9HLgJoNtPM8fA4rk5S2Q/HPiB6Y5vwJGep67+PjQJf9AUF8wQVfnj+ngAAAABJRU5ErkJggg==';
  
      star.onload = function () {
          var size = starSize;
          // init 60 stars in each rotate (for star is a regular hexagon)
          for (var i = 0; i &lt; 60; i++) {
              var canvas = document.createElement('canvas');
              var ctx = canvas.getContext('2d');
              canvas.width = size;
              canvas.height = size;
              ctx.translate(size / 2, size / 2);
              ctx.rotate(i * Math.PI / 180);
              ctx.translate(-size / 2, -size / 2);
              ctx.drawImage(star, 0, 0);
              starShapeList.push(canvas);
          }
  
          // start animation
          animate();
      }
  
  }
  
  function createCanvas() {
      var canvas = document.createElement('canvas');
      canvas.style.width = width + 'px';
      canvas.style.height = height + 'px';
      canvas.width = width * window.devicePixelRatio;
      canvas.height = height * window.devicePixelRatio;
  
      container.appendChild(canvas);
      canvasList.push(canvas);
      // return the ctx of created canvas
      return canvas.getContext('2d');
  }
  
  function Star() {
      // pick a random shape
      this.canvas = starShapeList[_.random(starShapeList.length - 1)];
  
      this.size = starSize;
      this.scale = 0.01;
      // set a random max scale
      this.maxScale = _.random(60, 120) / 100;
      // set a random position
      this.position = {
          x: _.random(width),
          y: _.random(height)
      };
  
      // start a scale animation
      new TWEEN.Tween(this)
          .to({
              scale: this.maxScale
          }, 1000)
          .start()
  }
  
  function animate() {
      // log time per frame
      console.timeEnd('per frame');
      console.time('per frame');
      requestAnimationFrame(animate);
      render();
  }
  
  function render() {
      // update tween
      TWEEN.update();
  
      // clear
      starCtx.clearRect(0, 0, width, height);
      // draw each star in star list
      starList.forEach(function (item) {
          // get current size
          var size = item.size * item.scale;
          starCtx.drawImage(item.canvas, 0, 0, item.size, item.size, item.position.x - size / 2, item.position.y - size / 2, size, size);
      });
  
      // create 10 stars per frame
      for (var i = 0; i &lt; 10; i++) {
          starList.push(new Star());
      }
  
      // when star count reached max star count per canvas
      if (starList.length &gt; starCountPerCanvas) {
          // create a new canvas
          starCtx = createCanvas();
          // clear star list
          starList.length = 0;
          // when canvas count reached max canvas count, fade out and remove the very first one
          if (canvasList.length &gt; maxCanvasCount) {
              var c = canvasList.shift();
              $(c).fadeOut(1000, function () {
                  this.remove();
              });
          }
      }
  }
  
  window.onload = function () {
      document.body.appendChild(container);
  }</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>* {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
  }
  
  body {
      background-color: black;
  }
  
  canvas {
      position: absolute;
      top: 0;
      left: 0;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;!DOCTYPE html&gt;
  &lt;html lang="en"&gt;
  &lt;head&gt;
      &lt;meta charset="UTF-8"&gt;
      &lt;title&gt;Test&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;script src="http://cdn.bootcss.com/underscore.js/1.8.3/underscore-min.js"&gt;&lt;/script&gt;
    &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/16.3.5/Tween.min.js"&gt;&lt;/script&gt;
  &lt;/body&gt;
  &lt;/html&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p><strong>Confirmed it was a Chrome Bug, works fine in IE 11 and FireFox</strong></p>